MSDN Magazin > Home > Ausgaben > 2008 > May >  Cutting Edge: Single Page Interface und AJAX-Mu...
Cutting Edge
Single Page Interface und AJAX-Muster
Dino Esposito

Codedownload verfügbar unter: CuttingEdge2008_05.exe (203 KB)
Browse the Code Online
Im Vergleich zum Entwicklungsparadigma für den Großteil heutiger Webanwendungen stellt AJAX für Architekten von Weblösungen einen Paradigmenwechsel dar. AJAX basiert auf einigen neuen Prinzipien und Regeln, mit denen das Verhalten eines webbasierten Systems erklärt wird. Für deren Implementierung sind einige neue Algorithmen erforderlich.
Das Hauptprinzip von AJAX besteht darin, dass Benutzer unformatierte Daten an den Webserver senden und unformatierte Daten empfangen.
Das zweite AJAX-Prinzip besteht darin, dass Benutzer Vorgänge selbstständig organisieren und somit den Hostbrowser und dessen Arbeitsweise zum Anfordern/Senden einzelner Seiten umgehen.
Das dritte AJAX-Prinzip besteht darin, dass der Clientcode für die Aktualisierung der Benutzeroberfläche verantwortlich ist, wobei die unformatierten Daten, die vom Server empfangen wurden, zu verwenden sind.
In diesem Artikel werden die Grundlagen für Entwickler vorgestellt, die die eher defensive AJAX-Implementierung durch partielles Rendering ersetzen möchten. Partielles Rendering bietet eine Möglichkeit, einige AJAX-Funktionen innerhalb der vorhandenen Web Forms-Architektur zu verwenden. Das AJAX-Paradigma basiert auf neuen Prinzipien, die neue Entwurfsmuster erfordern.

Auswirkungen des AJAX-Paradigmas
Bei partiellem Rendering mit ASP.NET handelt es sich um einen intelligenten Zusatz, der auf dem klassischen Web Forms-Postbackmodell aufbaut. Das bedeutet, dass eine Seite, die partielles Rendering verwendet, über die gleiche Postbackarchitektur und den gleichen Lebenszyklus wie eine Seite verfügt, für die AJAX nicht verwendet wird (siehe Abbildung 1). Der Unterschied liegt in einem clientseitigen Interceptor, der einfach die Standardaktion des Browsers, d. h. die Formularübertragung, verhindert und durch eine XMLHttpRequest-HTTP-Anforderung ersetzt (siehe Abbildung 2). Somit muss der Benutzer keine Seitenaktualisierung durchführen, und Entwickler umgehen stundenlange Schulungen für eine neue Architektur und neue Muster.
Abbildung 1 Traditioneller ganzseitiger Postbackvorgang (Klicken Sie zum Vergrößern auf das Bild)
Abbildung 2 Partielles AJAX-XMLHttpRequest-Rendering (Klicken Sie zum Vergrößern auf das Bild)
Selbstverständlich bietet partielles Rendering grafische Vorteile im Kontext der aktuellen Seite. Wenn Ihre Anwendung über eine Sammlung einzelner Seiten entworfen wurde, erfordert der Übergang von einer Seite zur nächsten immer noch ein Neuladen der gesamten Seite. Partielles Rendering eignet sich hervorragend zum Ersetzen von Postbacks innerhalb einer Seite, wie z. B. das Auslagern eines Rasters, zum Anpassen der Benutzeroberfläche nach einer Auswahländerung oder zum direkten Bearbeiten eines Datensatzes.
Da es sich bei partiellem Rendering nur um eine intelligente Form eines Seitenpostback handelt, gelten die gleichen architektonischen Einschränkungen wie beim Web Forms-Modell. Zum Beispiel darf lediglich eine ausstehende Anforderung pro Browserfenster existieren. Für das aktuelle Modell für Webanwendungen, d. h. beim Senden eines Formulars und Abrufen einer neuen Seite, ist diese Einschränkung nicht von großer Bedeutung.
Je intensiver sich Benutzer in AJAX einarbeiten, desto mehr erwarten sie, mehrere Aktivitäten gleichzeitig ausführen zu können. Bei partiellem Rendering können nicht zwei asynchrone Vorgänge gleichzeitig von Benutzern ausgeführt und abgeschlossen werden.
Partielles Rendering ist auf einen Anforderungsvorgang beschränkt, um die Konsistenz des Ansichtszustands zu gewährleisten. Hierbei handelt es sich um einen wesentlichen Bestandteil des Modells. Dies widerspricht dem ersten A in AJAX: asynchron. Mit partiellem Rendering sind Out-of-Band-Javascript-Postbacks zwar möglich, allerdings immer nur eines auf einmal. Wenn ein zweiter Vorgang ausgelöst wird, bevor der erste abgeschlossen wurde, wird der ausstehende Vorgang abgebrochen, damit der neue Vorgang durchgeführt werden kann. Die Richtlinie „Letzter gewinnt“ kann in „Erster gewinnt“ umprogrammiert werden, wobei der aktuelle Vorgang behalten und der neue Vorgang vom System ignoriert wird. Es bleibt jedoch bei der Tatsache, dass immer nur ein Vorgang auf einmal möglich ist.

Single Page Interface-Modell
Um alle Vorteile von AJAX nutzen zu können, müssen sich mehr oder weniger alle Features auf einer einzigen Seite befinden. Dies ist als SPI-Modell (Single Page Interface) bekannt. Beim SPI-Modell finden alle Interaktionen zwischen dem Browser und einer Webanwendung innerhalb der Begrenzungen einer Seite statt. Dieser Ansatz ist für das Web revolutionär, stellt jedoch nichts Neues für die Windows®- und Desktopentwicklung dar. Letztendlich handelt es sich bei dem SPI-Modell um nichts anderes als eine Windows-Anwendung mit einem bestimmten Hauptfenster.
Im SPI-Modell handelt es sich bei der Hauptseite um eine Kombination aus visuellen Elementen, die geladen, aktualisiert und unabhängig voneinander ausgetauscht werden können (siehe Abbildung 3). In diesem Fall muss eine Seite nicht komplett neu geladen werden, wenn eine Benutzeraktion erfolgt ist. Zu jedem Zeitpunkt werden nur visuelle Elemente und Inhalte angezeigt, die für den aktuellen Zustand der Anwendung relevant sind. Alle anderen Informationen werden ausgeblendet. Diese werden angezeigt, sobald sie für den Anwendungsfluss benötigt werden.
Abbildung 3 Single Page Interface-Elemente innerhalb einer Seite (Klicken Sie zum Vergrößern auf das Bild)
Das SPI-Modell aktiviert einige interaktive Features, z. B. direkte Bearbeitung, kontextbezogene Benutzeroberfläche, unmittelbare Benutzerfeedbackanfragen und asynchrone Vorgänge. Neben der Leistung und Reaktionsfähigkeit des SPI-Modells liegt der Hauptvorteil des Modells in der deutlichen Verbesserung der Benutzerfunktionalität.
Trotz all dieser Vorteile sollte nicht vergessen werden, dass der Entwurf einer neuen Anwendung mit dem SPI-Modell eine Herausforderung darstellt, da keine bewährten Muster oder Methoden vorhanden sind. Letztendlich gibt es aber eine einfache Möglichkeit, AJAX vorteilhaft in den meisten Unternehmen und Situationen einzusetzen. Neben diesem einfachen Weg gibt es auch einen nicht ganz so einfachen Weg zum Einsatz von AJAX, der an Bedeutung gewinnt.
Zum Entwickeln reiner AJAX-Anwendungen benötigen Sie eine gute Bibliothek an Steuerelementen für die Benutzeroberfläche, mit denen Effekte und spezielle Verhaltensweisen erreicht werden können. Sie benötigen ein reichhaltiges und anpassbares Dokumentobjektmodell (DOM), das auf dem standardmäßigen DOM des World Wide Web-Konsortiums (W3C) basiert und dennoch eine Definition Ihres eigenen anwendungsspezifischen Modells ermöglicht. Und schließlich benötigen Sie ein Server- und Clientframework für das einfache und effektive Entwickeln der Benutzeroberfläche und Codebehindskripts. Idealerweise verfügen Sie auch über Tools zum Debuggen und Testen.
Einige dieser Tools werden von Microsoft und anderen Anbietern angeboten. Hierfür stehen einige Benutzeroberflächen-Widgetbibliotheken zur Verfügung, sowie mehrere Anbieter, die Steuerelemente für die Definition eigener clientseitiger Objektmodelle bieten. Wirklich hilfreich wäre ein verbessertes AJAX-Framework, das speziell als Alternative zu Web Forms entworfen wurde und auf dem SPI-Modell basiert.
Das MVC-Framework (Model View Controller) ist ein solches alternatives Programmiermodell, das in der ASP.NET 3.5 Extensions-Bibliothek enthalten ist. In der aktuellen Form hat es jedoch nicht viel mit AJAX gemeinsam. Obwohl es die Implementierung von AJAX-Features nicht verhindert, eignet es sich nicht für die Weiterentwicklung in ein SPI-Modell. Dies kann sich jedoch mit der Zeit ändern.
Im SPI-Modell zeigt die Hauptseite auf HTTP-Endpunkte in der gleichen Anwendung. Das Model führt Remotecode aus, lädt aber nicht die ganze Seite neu. Es aktualisiert die Benutzeroberfläche über Steuerelemente, die sowohl HTML als auch Skript verwenden. Diese Steuerelemente könnten möglicherweise intelligent genug sein, um den Großteil des Javascript-Codes zu erstellen, die sie erfordern. Stellen wir uns z. B. ein Formular zum Buchen von Flügen vor, das über zwei mögliche Suchparameter verfügt: Uhrzeit und Preis. Wenn der Benutzer am kostengünstigsten Flug interessiert ist, muss die Dropdownliste mit den Stunden nicht angezeigt werden. Wenn der Benutzer zu einer bestimmten Uhrzeit fliegen möchte, muss der HTML-Code aufgerufen werden, über den die Stunden angezeigt werden.
Diese Funktion zum Ein- und Ausblenden kann sehr einfach mittels JavaScript umgesetzt werden. Heutzutage ist der Entwickler der Seite für das Schreiben dieses Codes verantwortlich. Steuerelemente wie CollapsiblePanel aus dem ASP.NET AJAX Control Kit (asp.net/AJAX/AjaxControlToolkit/Samples/CollapsiblePanel/CollapsiblePanel.aspx) können hierbei helfen.

Nachteile des Single Page Interface-Modells
Obwohl das SPI-Modell mit dem gesamten AJAX-Paradigma, das hierbei eingesetzt wird, eine wesentlich interaktivere Benutzerfunktionalität bietet, gibt es doch einige Probleme mit Durchsuchbarkeit, Verlaufsverwaltung, Eingabehilfen und Offlineunterstützung. Jahrelang wurden Webseiten mithilfe permanenter Verbindungen nachverfolgt. Suchmaschinen basierten auf dem Zuordnen von Schlüsselwörtern zu einer oder mehreren URLs. Bei diesem Modell wurde davon ausgegangen, dass jeder Zustand in einer Webanwendung einer Seite und einer bestimmten URL entspricht.
Im SPI-Modell in AJAX ist diese Annahme nicht mehr gültig. Wenn alle (oder die meisten) Vorgänge innerhalb der gleichen Seite ausgeführt werden, ist der URL-Übergang zum Kennzeichnen eines neuen oder geänderten Zustands oder Websiteinhalts nicht mehr vorhanden. Daher gibt es auch keinen einfachen Weg, Inhalt (und Schlüsselwörter) einer eindeutigen URL zuzuordnen. Dieser Aspekt des SPI-Modells wirkt sich auf die Durchsuchbarkeit und die Verlaufsverwaltung aus (z. B. die Verwendung der Schaltflächen „Zurück“ und „Vorwärts“).
Der Browserverlauf wird letztendlich möglicherweise ein veraltetes Konzept darstellen, das lediglich in klassischen, statischen Webmodellen eingesetzt wird. Es muss jedoch bedacht werden, dass Benutzer mit der Verwendung dieser Schaltflächen so vertraut sind, dass diese nicht einfach nur deaktiviert werden können.
Eingabehilfe ist ein weiteres Problem bei AJAX-Anwendungen. Die am häufigsten verwendeten Sprachausgaben haben große Schwierigkeiten mit Inhalten, die über DOM-Skripts generiert wurden. Alle Formen von AJAX (einschließlich partiellem Rendering) basieren entsprechend ihrem Entwurf auf DOM-Skripts. Eingabehilfe muss daher über andere Wege bereitgestellt werden.
In Abschnitt 508 der Web Content Accessibility Guidelines (WCAG) wird empfohlen, dass Seiten über alternativen funktionalen Text verfügen, der von Hilfstechnologien gelesen werden kann, wenn Skriptsprachen zum Anzeigen von Inhalt oder zum Erstellen visueller Elemente verwendet werden. Das <noscript>-Tag erfüllt die Anforderungen dieser Empfehlung. Derzeit führt der Großteil der AJAX-Frameworks dynamische Aktualisierungen innerhalb der Seite durch, ohne statische Informationen zu aktualisieren, die sich in den <noscript>-Tags befinden.

Zugängliche reichhaltige Internetanwendungen
Hierbei scheint es sich um ein doppeltes Problem zu handeln, dass sowohl AJAX-Anwendungen als auch die Technologie von Bildschirmsprachausgaben betrifft. Auf der einen Seite gibt es Bildschirmsprachausgaben, die einige Clientereignisse interpretieren können: z. B. „onclick“, „keypress“ und „readystatechange“. Bildschirmsprachausgaben mit dieser Fähigkeit könnten es ermöglichen, vielen AJAX-basierten Anwendungen zumindest eine erste Stufe von Eingabehilfen hinzuzufügen.
Auf der anderen Seite geben Bildschirmsprachausgaben in der Regel keine neuen Informationen aus, nachdem das anfängliche Ereignis für das Laden der Seite im DOM ausgeführt wurde. Es gibt jedoch einige Tricks, mit denen Sie der Bildschirmsprachausgabe mitteilen können, dass etwas geändert wurde. Eine der effektivsten Möglichkeiten besteht darin, die Eigenschaft „tabindex“ im Stamm der aktualisierten DOM-Struktur auf -1 zu setzen. Hierbei handelt es sich aber nur um einen Trick. Für das Problem der Eingabehilfen ist eine umfassendere AJAX-Lösung erforderlich.
Eine mögliche Lösung hierfür ist der neu entwickelte Standard von W3C namens „Accessible Rich Internet Applications“ (ARIA), der hauptsächlich aus sprachausgabespezifischen Erweiterungen von HTML-Tags besteht. Einige der häufig verwendeten clientseitigen AJAX-Bibliotheken unterstützen bereits manche dieser ARIA-Features. Bei dem Problem handelt es sich jedoch nicht nur um die Verfügbarkeit eines AJAX-kompatiblen Standards für Eingabehilfen. Das Problem betrifft auch (wenn nicht sogar hauptsächlich) Inhalte (sowohl Markups als auch Skripts), die von Serversteuerelementen ausgegeben werden.
Wie sieht es mit Offlineanwendungen aus? Viele Entwickler sind der Meinung, dass Offline-AJAX-Anwendungen nicht realisierbar sind, da AJAX-Anwendungen vollständig auf dem Internet basieren. Meiner Meinung nach ist dies ein wenig zu vereinfacht dargestellt, allerdings auch nicht ganz falsch. Heutzutage basieren fast alle Webanwendungen, AJAX- und Nicht-AJAX-Anwendungen auf dem Internet oder einem Intranet.
Nicht-AJAX-Anwendungen können auf jeden Fall offline verwendet werden. Für die Verlaufsverwaltung ist z. B. lediglich die Offlinenavigation im Browser erforderlich. In einer klassischen Webanwendung wird jede HTTP-Anforderung vom Browser verwaltet. Wenn keine Verbindung verfügbar ist (und bevor ein HTTP 404-Fehler ausgegeben wird), sucht der Browser im lokalen Seitencache.
AJAX-Anwendungen unterscheiden sich von klassischen Webanwendungen in der Hinsicht, dass das XMLHttpRequest-Objekt statt des Browsermoduls zum Senden von HTTP-Anforderungen verwendet wird. Um Offlineszenarios für AJAX-Anwendungen zu unterstützen, muss dem XMLHttpRequest-Objekt entweder Zugriff auf den Browsercache eingeräumt werden, oder das Objekt muss in der Lage sein, einen eigenen Cache bereits aufgerufener Seiten zu erstellen und zu verwalten. Einige AJAX-Frameworks beginnen bereits damit, diese Funktion zu integrieren. Hierbei handelt es sich jedoch um eine nicht ganz einfache Aufgabe, da der Zugriff auf den Datenträger innerhalb des JavaScript-Codes erfolgen muss.

Eine kurze Führung durch AJAX-Muster
Die nächste Generation webbasierter Anwendungen führt direkt zu AJAX bzw. zu Rich Internet Applications (RIA). Es gibt drei Hauptanwendungskategorien, die diese Entwicklung anfänglich anführten: klassische HTML-basierte Websites, Hybridanwendungen zur Integration mehrerer Systeme in einem einzelnen webbasierten Front-End sowie Thick Clients.
Für die erste Kategorie stellt das partielle Laden der Benutzeroberflächen (partielles Rendering) eine einfache Möglichkeit zur Implementierung von AJAX mit geringen Auswirkungen auf vorhandenen Code und vorhandene Fähigkeiten dar.
Das Konzept von Hybridanwendungen eignet sich nicht unbedingt für AJAX und bietet keine verbesserte Benutzerinteraktion. Hierbei handelt es sich vielmehr um eine Möglichkeit, Daten verschiedener Quellen zu erfassen und in einer einheitlichen und zusammenhängenden Benutzeroberfläche zusammenzufassen. Dies kann auch in einem klassischen Server-zu-Server-Szenario geschehen. Mit AJAX ist dies jedoch einfacher und überzeugender. Aus AJAX-Perspektive benötigt eine Hybridanwendung Standardformate für die Datenserialisierung (Syndikation), ein einfaches Framework für das Aufrufen von Remotediensten über Skripts, ein aktualisierbares DOM und möglicherweise einige reichhaltige visuelle Steuerelemente mit einem geeigneten Programmiermodell.
Das Erstellen von Thick Clients stellt in AJAX die größte Herausforderung dar. Bei einem Thick Client kann es sich um das Front-End eines verteilten Unternehmenssystems oder vielleicht die Darstellungsschicht einer Branchenanwendung handeln. Ein Thick Client kann auch als eigenständige Anwendung fungieren, die von einer IT-Abteilung als Webanwendung verfügbar gemacht wird. Diese Anwendungen benötigen die Reichhaltigkeit und Geschwindigkeit herkömmlicher Desktopbenutzeroberflächen, unabhängig davon, ob sie im Internet veröffentlicht oder auf ein Intranet beschränkt sind.
Im Vergleich zur Windows-Entwicklung ist das Web in Bezug auf Interaktivität und Reaktionsfähigkeit einen Schritt zurück. Mit AJAX stehen nun endlich die Tools (und Umgebungsbedingungen) zur Verfügung, um ein grundlegend verschiedenes Modell zu entwickeln. Hierbei gibt es jedoch einen großen Nachteil. Auf der einen Seite gibt es Millionen von Benutzern und Entwicklern, die an das herkömmliche Web mit Funktionen wie Verlauf, Offlinenavigation, Favoriten, einzelnen Vorgängen, Seitenübergängen und permanente Verbindungen gewöhnt sind. Auf der anderen Seite gibt es AJAX mit dem Konzept simultaner Vorgänge und einer einzelnen Benutzeroberfläche, die automatisch aktualisiert wird. Das AJAX-Modell erfordert, dass Benutzeraufgaben vollständig rückgängig gemacht werden können. Die Browserfeatures für Verlauf und Seitennavigation sind hier nicht ausreichend.
Für das Codieren ist beim SPI-Modell ein neuer Satz an Entwurfsmustern notwendig. Abbildung 4 zeigt einige der am häufigsten verwendeten AJAX-Muster. Der Großteil konzentriert sich auf Benutzeroberflächenverfahren und -anordnungen. Beachten Sie jedoch, dass einige beliebte AJAX-Muster und -Methoden, die bereits in der Microsoft® AJAX-Clientbibliothek implementiert sind, nicht in dieser Liste enthalten sind. So ist z. B. ein AJAX-Stub, ein browserübergreifendes JavaScript-Modell oder ein Aufrufverfolgungsmodell nicht erforderlich, wenn Sie ASP.NET AJAX verwenden. Diese Features sind in AJAX standardmäßig verfügbar.

Muster Ziel
Browser-Side Templating Bei diesem Muster wird die Verwendung von HTML-Vorlagen vorgeschlagen, die dynamisch mit Daten ausgestattet werden, die von HTTP-Remoteendpunkten abgerufen werden. Statt des dynamischen neuen Generierens des HTML-Layouts für die Daten pro Anforderung, schlägt das Muster vor, eine eigene Vorlagenschicht einzurichten. Dieses Muster stellt eine Alternative zum HTML Message-Muster dar.
Cross-Domain Proxy Das Muster betreibt eine Server-zu-Server-Verbindung zu einem erreichbaren und öffentlich verfügbaren Dienst und überträgt Daten zurück zum Client. AJAX-Anwendungen können keine Verbindung vom Clientbrowser zu URLs außerhalb der Domäne der Seite herstellen. Ein lokaler Proxy, der sich in der gleichen Domäne befindet, kann Daten aber problemlos von beliebigen Orten abrufen und zum Aufrufer übertragen.
Heartbeat Weil die meisten AJAX-Anwendungen zahlreiche Vorgänge auf dem Client ausführen, ohne jemals Daten zurückzusenden, ist es möglicherweise erforderlich, dem Server mitzuteilen, dass ein bestimmter Client weiterhin aktiv ist. Das Muster schlägt vor, dass die Clientanwendung regelmäßig eine Taktmeldung hochlädt, um anzugeben, dass die Anwendung weiterhin geladen ist und im Browser ausgeführt wird.
HTML Message HTTP-Remoteendpunkte geben in der Regel JSON-Daten (JavaScript Object Notation) an den Client zurück, die in das vorhandene DOM integriert werden. Diese Aufgabe kann nur über JavaScript durchgeführt werden. Wenn der Clientcode aber besonders komplex ist oder eine gesteigerte Leistung gewünscht wird, ist es möglicherweise günstiger, HTML (Daten und Layout) statt lediglich einfache Daten vom Server zurückzugeben.
Microlink AJAX wird vorwiegend zum Ausführen zahlreicher Aktivitäten innerhalb der gleichen Seite verwendet. Wie würden Sie auf externe Inhalte, d. h. Inhalte für andere Seiten, in einer klassischen Webanwendung verweisen? Hierfür wird ein Hyperlink innerhalb der Seite benötigt, ein so genannter Microlink. Ein Microlink ist ein Verweis auf einen Teil des Markup, der über Serveraufrufe abgerufen und dann in die Seite eingefügt wird. Bei einem Microlink kann es sich um einen HTTP-Endpunkt oder eine Methode eines JavaScript-Befehlsobjekts handeln.
On-Demand JavaScript Hierbei handelt es sich um das JavaScript-Gegenstück zu häufig verwendeten Mustern mit verzögertem Laden, die in einer Datenzugriffsschicht verwendet werden. Das Herunterladen des erforderlichen JavaScript während der Seiteninitialisierung kann sich auf die Leistung auswirken und den ganzen Prozess verlangsamen. Durch das Laden von JavaScript-Dateien pro Aufforderung können Seiten wesentlich schneller geladen werden, ohne dass die Funktionalität eingeschränkt wird.
Page Arrangement Da der Großteil der Aktivität einer Anwendung auf der gleichen Seite stattfindet, müssen der Inhalt der Seite aktualisiert und neue Informationen angezeigt werden, sobald sich der Kontext ändert. Dieses Muster schlägt vor, dass Sie einfach das DOM verwenden, um Elemente hinzuzufügen/zu entfernen oder anzuzeigen/auszublenden, um Änderungen des Zustands widerzuspiegeln.
Periodic Refresh Der Browser plant eine regelmäßige Anforderung zum Abrufen neuer und aktueller Informationen, um die Benutzeroberfläche zu aktualisieren.
Popup Das Muster stellt die Webversion von modalen/nicht modalen Windows-Dialogfeldern dar. Ein Popup verfügt über HTML-Inhalt, der (für einen relativ kurzen Zeitraum bzw. bis der Benutzer das Popup schließt) über dem vorhandenen Inhalt angezeigt wird.
Predictive Fetch Das Muster schlägt vor, die wahrscheinlichsten Benutzeraktionen vorherzusagen und die erforderlichen Daten im Voraus abzurufen. Die Implementierung dieses Musters hat jedoch einen Preis: Es handelt sich hierbei nur um eine Vorhersage, und die kann falsch sein. Obwohl das Muster die wahrgenommene Leistung wirksam steigern kann, ist auch ein Leistungsverlust möglich. Dies geschieht bei einer schlechten Implementierung oder einer Implementierung unter nicht idealen Bedingungen, wenn der Server eine hohe Bandbreitennutzung aufweist.
Progress Indicator Das Muster, das zur Überwachung des Fortschritts von Servervorgängen verwendet wird. Die Idee besteht darin, dass der Servervorgang seinen eigenen Fortschritt an einem freigegebenen Speicherort speichert, der von einem clientseitigen Überwachungsdienst im Rahmen einer Fortschrittsaktualisierung gelesen werden kann.
Submission Throttling Einer der potenziellen Nachteile von AJAX besteht darin, dass innerhalb eines bestimmten Zeitraums möglicherweise zu viele Anforderungen an den Server gesendet werden. Wenn dies der Fall ist, liegt ein Problem mit der Skalierbarkeit vor. Dieses Muster schlägt vor, dass ein Zeitgeber zum regelmäßigen Hochladen der Daten an den Server sowie ein lokaler Cache oder eine Warteschlage zum Sammeln von Anforderungen verwendet wird.
Timeout Bei aufwändigen Clientvorgängen wie Streaming oder periodischer Aktualisierung ist es schwierig sicherzustellen, dass alle verbundenen Clients die Anwendung auch tatsächlich verwenden. Dieses Muster schlägt vor, dass Sie den aufwändigen Vorgang abbrechen und nur bei ausdrücklicher Aufforderung durch den Benutzer fortsetzen.
Unique URLs Mit diesem Muster können Sie den unterschiedlichen Bereichen Ihrer Anwendung, die sich in der Regel in verschiedenen Zuständen befinden, bestimmte URLs zuweisen. Dieses Muster wird häufig zur Verlaufsunterstützung in AJAX-Anwendungen verwendet.
Virtual Workspace Der Server muss auf Anforderungen so schnell wie möglich antworten, kann aber möglicherweise nicht alle Daten sofort zurückgeben, wenn die erforderliche Bandbreite nicht verfügbar ist. Dieses Muster schlägt vor, dass Sie eine virtuelle Benutzeroberfläche erstellen, die den Eindruck erweckt, dass alle Daten verfügbar sind, während sich nur ein kleiner Teil davon tatsächlich auf dem Client befindet. Die Anwendung ist für das Herunterladen von Daten bei Bedarf sowie für die Speicherung im lokalen Cache verantwortlich.
Beachten Sie auch, dass die Muster in Abbildung 4 und AJAX-Muster im Allgemeinen eher Referenzmuster als Entwurfsmuster darstellen. Die Muster zeigen häufig eingesetzte Methoden, beziehen sich aber nicht zwangsläufig auf entwurfsbezogene Probleme.
In Abbildung 4 sind die Hauptmerkmale der einzelnen Muster kurz aufgeführt. Im weiteren Verlauf dieses Artikels werde ich einige dieser Muster genauer beschreiben. In zukünftigen Artikeln werde ich mich mit weiteren wichtigen Mustern befassen, deren Hauptmerkmale diskutieren und praktische Implementierungen vorführen. (Eine hervorragende Website zu AJAX-Mustern ist ajaxpatterns.org.)

Das Muster „Unique URLs“
URLs bilden den Kern des Web. Benutzer speichern URL-Favoriten für zukünftige Verfügbarkeit, folgen URLs zu neuen Inhalten und verwenden URLs, um zu einem früheren Zustand zurückzukehren. Mit AJAX und dem SPI-Modell kann eine Anwendung mehrere Aufgaben innerhalb einer einzelnen URL ausführen. Dies stellt eine Bedrohung für eine zentrale Säule der Weberfahrung dar: dass der diskrete Zustand einer Anwendung durch eine bestimmte URL identifiziert wird.
Browser erstellen, während Benutzer navigieren, ihre eigenen Caches mit URLs. Bei AJAX werden viele Vorgänge nicht über den Browser durchgeführt und nicht in die Liste aufgerufener URLs aufgenommen, die von den Menüs „Vorwärts“ und „Zurück“ verwendet werden. Andererseits stellen Clientbrowser kein Programmiermodell für JavaScript-Code zur Verfügung, mit dem URLs der Liste hinzugefügt werden können. Das Browserobjektmodell stellt lediglich Methoden zum Vorwärts- und Rückwärtsnavigieren innerhalb der vorhandenen Liste bereit.
Über das Muster „Unique URLs“ wird jedem wichtigen Anwendungszustand eine eindeutige und aussagekräftige URL zugewiesen. Wenn der Benutzer z. B. einen Wert auf einer AJAX-Seite bearbeitet, sollte dem Browsercache eine neue URL hinzugefügt werden, auch wenn der Vorgang über XMLHttpRequest innerhalb der gleichen Seite erfolgt ist.
Ein Änderung der URL ohne Neuladen der Seite erfolgt über den folgenden JavaScript-Code:
window.location.hash = stateInfo;
Über diesen Code wird der URL ein Fragment mit dem Präfix # hinzugefügt:
http://www.contoso.com/shopping.aspx#edit-1234
Bei Verwendung dieses Musters ändert sich die URL, wenn Sie einen beliebigen AJAX-Vorgang starten, wodurch die Änderungen des Anwendungszustands vom Browser nachverfolgt werden können.
Dies umfasst jedoch mehr als lediglich das Aufzeichnen der URL. Beim Umleiten des Browsers zu einer hashbasierten URL wird zunächst die Haupt-URL geladen und dann nach einem Seitenfragment mit dem Hashnamen gesucht. In AJAX zeigt der Hashname nicht auf ein tatsächliches Seitenfragment, sondern auf anwendungsspezifische Informationen, die den aktuellen Zustand repräsentieren. So könnte „edit-1234“ z. B. anzeigen, dass Sie ein Element mit der ID 1234 bearbeitet haben. Das eigentliche Format ist beliebig anpassbar.
Wenn der Browser das richtige Fragment nicht finden kann, wird die Hash-URL ignoriert. Demzufolge wird die Seite zwar vom Benutzer geladen, aber nicht zwangsläufig im erwarteten Anwendungszustand. Hier ist ein zweiter Trick erforderlich. Das Ereignis zum Laden der Seite muss abgefangen, die URL analysiert, der Hashwert extrahiert und der JavaScript-Code, mit dem die Seite im gewünschten Zustand aufgerufen wird, ausgeführt werden:
window.onload = function() {
    checkAndParseURL();
}
 
checkAndParseURL() {
     var state = window.location.hash;
     restorePage(state);
}
Ein ähnlicher Ansatz ist in der Verlaufsunterstützung implementiert, die in ASP.NET 3.5 Extensions verfügbar ist. Weitere Informationen hierzu finden Sie unter quickstarts.asp.net/3-5-extensions/ajax. Die Lösung in ASP.NET 3.5 Extensions ist vollständig in das Framework integriert. Sie ist an neuen Eigenschaften und Ereignissen zu erkennen, die dem ScriptManager-Steuerelement hinzugefügt wurden. Letztendlich handelt es sich jedoch um die Implementierung des Musters „Unique URLs“.
Beachten Sie auch, dass die genannte Vorgehensweise mit dem URL-Hash nicht in Internet Explorer® funktioniert, da Internet Explorer Hashänderungen für URLs mit Ausnahme von Inlineframes nicht anerkennt. Tatsächlich behandeln alle Browser die Fragmentnavigation auf unterschiedliche Weise (weitere Informationen hierzu finden Sie unter weblogs.asp.net/bleroy/archive/2007/09/07/how-to-build-a-cross-browser-history-management-system.aspx). Die Lösung in ASP.NET 3.5 Extensions berücksichtigt diesen Unterschied und stellt daher einen wirklich browserübergreifenden Trick dar.

Das Muster „Timeout“
Einer der größten Vorteile von AJAX ist die Möglichkeit, Seitenaktualisierungen in Echtzeit zu implementieren. Aktualisierungen in Echtzeit können jedoch leicht zu einer Gefahr werden, wenn sie missbräuchlich durchgeführt werden. Betrachten wir ein Szenario, in dem ein Benutzer eine Liveseite anzeigt, die alle paar Sekunden eine Abfrage nach aktualisierten Daten an den Server sendet. Gehen wir davon aus, dass der Benutzer den Computer stundenlang verlässt, ohne den Browser zu schließen. Die Seite sendet weiterhin Abfragen an den Server und generiert so eine bedeutende und unnötige Arbeitsauslastung für den Server.
Wie können Sie bestimmen, ob ein Timeout für die Clientsitzung aufgetreten ist? Auf dem Server gibt es Sitzungstimeouts, aber in AJAX sind auch die Clientsitzungen von Bedeutung. Um das Ende einer Clientsitzung zu erkennen, müssen Sie prüfen, ob in einem bestimmten Zeitraum Benutzeraktivitäten, z. B. Klicken oder Tastatureingaben, stattgefunden haben. Die Überwachung der Tastatur- und Mausaktivität kann sich jedoch als schwierig erweisen. Der Einsatz von Zeitgebern ist in der Regel einfacher und effektiver.
Um das Ende einer Sitzung mithilfe eines Zeitgebers zu erkennen, wird ein Clientzeitgeber eingerichtet, der nach einer bestimmten Anzahl von Sekunden (oder Minuten) abläuft, die aktuelle Aufgabe abbricht und ein Dialogfeld mit einer Warnung anzeigt. Wenn der Benutzer auf die Eingabeaufforderung reagiert, wird die Verarbeitung fortgeführt.
In Abbildung 5 finden Sie den wesentlichen Teil des Javascript-Codes für das Muster „Timeout“. Auf der Beispielseite ist eine Uhr eingebettet. Die Uhr wird über ein Label-Steuerelement in einem UpdatePanel implementiert, das regelmäßig von einem Timer-Steuerelement aktualisiert wird:
<script type="text/javascript">
    var timer = null;
    function pageLoad()
    {
        if (timer === null)
        {
            timer = new Samples.TaskTimer(5000, stopTask);
            timer.start();
        }
    }

    function pageUnload()
    {
        if (timer != null)
            timer.stop();
    }

    
    function stopTask()
    {
        // Stop the clock 
        var clock = $find("<%= Timer1.ClientID%>");
        clock._stopTimer();
        
        AskIfTheUserWantsToContinue();
    }
    
    function AskIfTheUserWantsToContinue()
    {
        // Ask if the user wants to continue
        var answer = window.confirm(
          "Is it OK to continue with the clock?");
        if (answer)
        {
            // Restart the task  
            var clock = $find("<%= Timer1.ClientID%>");
            clock._startTimer();
            
            // Restart our own timeout engine
            if (timer !== null)
                timer.start();
            return;
        }        
    }
</script>

protected void Timer1_Tick(object sender, EventArgs e)
{
    Label1.Text = DateTime.Now.ToLongTimeString();
}
Die Uhr stellt jedoch eine aufwändige Aufgabe dar, die den Server mit Abfragen überschwemmen könnte. Die Idee besteht darin, einen Zeitgeber einzurichten, der die Benutzer regelmäßig fragt, ob sie wirklich fortfahren möchten. Über den Timeoutcode wird zuerst die Uhr gestoppt und dann das Dialogfeld angezeigt. In Abhängigkeit von der Antwort des Benutzers wird die Uhr dann neu gestartet.
Der Code verwendet die Funktion „$findet“ zum Suchen nach der ASP.NET AJAX-Komponente. In diesem Fall handelt es sich hierbei um das Clientobjektmodell des ASP.NET-Timer-Serversteuerelements. Abbildung 6 zeigt die Seite in Aktion mit einem Dialogfeld, in dem der Benutzer gefragt wird, ob mit der Verarbeitung fortgefahren werden soll.
Abbildung 6 Dialogfeld mit der Frage, ob fortgefahren werden soll (Klicken Sie zum Vergrößern auf das Bild)

Senden Sie Fragen und Kommentare für Dino Esposito (in englischer Sprache) an cutting@microsoft.com.


Dino Esposito ist der Autor von Programming ASP.NET 3.5 Core References. Er lebt in Italien und ist ein weltweit gefragter Referent bei Branchenveranstaltungen. Sie finden seinen Blog unter weblogs.asp.net/despos.

Page view tracker