Sie sind hier: Startseite | Wissen

Technische Einführung in die AJAX-Erweiterungen für ASP.NET 2.0

Autor: Dr. Holger Schwichtenberg, www.IT-Visions.de

Dieser Artikel ist ein Auszug aus dem Buch ".NET 3.0 Crashkurs" und beschäftigt sich mit den AJAX-Erweiterungen für die Webprogrammierung mit ASP.NET 2.0. Diese Erweiterungen sind nicht zusammen mit ASP.NET 2.0 im November 2005 erschienen und auch nicht zusammen mit .NET 3.0 im November 2006, sondern im Januar 2007 als eine kostenlos Erweiterung.

 

  HINWEIS        ASP.NET AJAX ist eine weitaus mächtigere Lösung als die in ASP.NET 2.0 enthaltenen Client-Rückrufe, die immer nur eine Ein- und eine Ausgabezeichenkette zuließen.

 

Web 2.0 und AJAX

Das Hype-Wort »Web 2.0« ist in aller Munde. Unter der technischen Seite von Web 2.0 verstehen viele eine neue Generation von Webanwendungen, bei denen mehr clientseitiger JavaScript-Code eingesetzt wird, um mit Webservern zu kommunizieren. Web 2.0 umfasst u. a. folgende Szenarien:

§     Austausch von Seitenteilen anstelle des ständigen Neuladens von kompletten Webseiten

§     Kopplung von verschiedenen serverseitigen Webanwendungen (sogenannte Mashups)

Basis für diese Web 2.0-Szenarien ist die Technologie Asynchronous JavaScript and XML (AJAX), die abseits der üblichen HTTP-Rundgänge (Roundtrips) Aufrufe des Webservers vom Browser ermöglicht. In den Aufrufen werden XML-Daten ausgetauscht, wobei die XML-Daten auf der Clientseite per JavaScript verpackt und über HTTP versendet werden. Die Aufrufe heißen daher auch XML-HTTP-Requests. Die XML-Antwort des Servers erhält der Client in der HTTP-Antwort. Durch die asynchrone Ausführung wird der Browser in der Zwischenzeit nicht blockiert. Eine komplementäre Technologie für AJAX ist das Document Object Model (DOM), das die dynamische Veränderung von im Browser dargestellten Seiten ermöglicht.

 

  HINWEIS        Wirklich neu an AJAX ist nur der Name, der erstmals im Februar 2005 von Jesse James Garrett in [JJG05] verwendet wurde. Die Idee des entfernten Prozeduraufrufs aus dem Browser heraus wurde erstmals schon im Jahr 1998 von Microsoft im Internet Explorer 4.0 in Form des MicrosoftRemote Scripting (MSRS) verwendet. MSRS basierte auf einem Java Applet. Im Internet Explorer 5.0 ist später das XmlHttpRequest-Objekt erschienen, das noch heute in dieser Form im Internet Explorer und anderen Browsern existiert und jetzt den Kern von AJAX bildet.

Im Internet Explorer bis Version 6.0 ist XML-HTTP durch ein COM-Objekt (Microsoft.XmlHttp ) realisiert, in Mozilla (Netspace, Firefox, Safari etc.) sowie im Internet Explorer 7.0 durch das eingebaute Objekt XmlHttpRequest . Neu ist, dass es sogenannte AJAX-Frameworks gibt, die die Handhabung dieses Objekts stark vereinfachen und eine Abstraktion bieten, sodass aus JavaScript heraus Funktionen eines Proxy aufgerufen werden, die auf dem Server als Funktionsaufrufe signalisiert werden.

 

 

  ACHTUNG        Aufgrund der Tatsache, dass die XML-HTTP-Unterstützung im Internet Explorer bis Version 6.0 ein COM-Objekt ist, kann AJAX dort nur funktionieren, wenn in den Sicherheitseinstellungen des Internet Explorers für die jeweilige Zone »Script ActiveX controls marked safe for scripting« aktiviert ist. Das XmlHttpRequest -Objekt liegt inzwischen dem W3C zur Standardisierung vor [W3C05].

 

Abbildung 21.1    AJAX im Vergleich zum klassischen Rundgangmodell

 

  WICHTIG        AJAX bedeutet auch neue Schwierigkeiten und Herausforderungen, insbesondere

§     in Hinblick auf Benutzer, die JavaScript deaktiviert haben

§     die »Zurück«-Funktion der Browser, die AJAX-Aufrufe nicht berücksichtigt, und

§     die Zugänglichkeit für Menschen mit körperlichen Einschränkungen.

Für eine detaillierte Diskussion von AJAX-Grundlagen sei hier auf [MiLe01] verwiesen.

 

Microsoft-AJAX Produkte

Microsofts Beitrag zum AJAX-Hype wurde ursprünglich auf der Professional Developer Conference (PDC) im September 2005 in Los Angeles angekündigt unter dem Codenamen »Atlas«. Das Erscheinen war für Ende 2007 im Rahmen von »Orcas« geplant. Aufgrund des Kundendrucks hat Microsoft dann aber einen Teil vorab veröffentlicht.

Die AJAX-Produktgruppe besteht daher aus folgenden Teilen:

§     Die Microsoft AJAX Library ist eine JavaScript-Bibliothek, die AJAX-Funktionen und JavaScript-Erweiterungen bereitstellt. Die Microsoft AJAX Library ist browserunabhängig (durch Abstraktion von der Implementierung des XmlHttpRequest -Objekts) und zudem unabhängig von der eingesetzten Servertechnologie. Microsoft liefert mit der ersten Version der AJAX Library eine Abstraktion für die Browser Internet Explorer, Firefox, Safari und Opera.

§     Die ASP.NET-AJAX-Erweiterungen (ASPAJAXExtSetup.msi) umfassen serverseitige Unterstützung für AJAX-Entwicklung und sind eine gute Ergänzung zu der Microsoft AJAX Library. Die beiden
wesentlichen Konzepte in den ASP.NET-AJAX-Erweiterungen sind hier die partielle Seitenerzeugung und die asynchronen Browser-Rückrufe an den Server.

§     Das optionale AJAX Control Toolkit geht über AJAX im engeren Sinne hinaus und stellt eine Sammlung von DHTML-Widgets für JavaScript-basierte Zusatzfunktionen im Browser bereit. Dazu gehören Eingabeprüfung, Navigationselemente und grafische Spielereien wie Schatten und Animationen.

Für Visual Studio gibt es zwar noch keine Assistenten, aber zumindest eine Projektvorlage sowie rudimentäre Unterstützung für den Webform-Designer und das Eigenschaftsfenster.

 

  HINWEIS        Nicht alle Konzepte aus dem Atlas-Projekt sind im Januar 2007 als endgültiges Produkt erschienen. Microsoft hat Atlas gespalten in einen Teil, der im Januar 2007 erschienen ist, und in einen Teil, der mit .NET 3.5 Ende 2007 erscheinen soll. Deshalb gibt es parallel zu der endgültigen Version von ASP.NET AJAX 1.0 bereits eine Vorabversion der zweiten Version unter dem Namen »ASP.NET AJAX Futures«.

 

Installationspakete und Quellcode

ASP.NET AJAX ist nicht Teil von .NET 3.0, sondern eine Ergänzung zu .NET 2.0, aber auch lauffähig auf einem Rechner mit .NET Framework 3.0. Mit .NET 3.5 (Ende 2007) will Microsoft die AJAX-Erweiterungen in den Kern von ASP.NET integrieren.

Auf dem Download-Server [ASPNET01] von Microsoft kann man die AJAX Library einzeln oder zusammen mit den ASP.NET-AJAX-Erweiterungen unter dem Namen ASP.NET AJAX beziehen. Das Control Toolkit gibt es bei dem Quellcode-Portal CodePlex [CODEPLEX02].

Zu allen drei Produkten hat Microsoft den Quellcode offengelegt und bietet beim Control Toolkit und der AJAX Library auch an, dass man den Code in veränderter Form weiterverbreiten darf. Der Quellcode des serverseitigen Teils ist aber auf den Einsatz beim Debugging beschränkt.

In Hinblick auf den clientseitigen Teil einer AJAX-Lösung schauen viele Webentwickler sehr argwöhnisch auf die Größe der einzubindenden JavaScript-Lösung. Die Microsoft AJAX Library umfasst drei JavaScript-Bibliotheken (MicrosoftAjax.js , MicrosoftAjaxTimer.js und MicrosoftAjaxWebForms.js ), die zur Laufzeit eine Größe von zusammen 113 KB haben. Zu allen drei Bibliotheken gibt es aber auch eine »Debug«-Variante mit Quellcodekommentaren, Quellcodeformatierung und sprechenden Variablennamen. Diese »Debug«-Variante umfasst zusammen 371 KB. Die ASP.NET-AJAX-Erweiterungen binden die »Debug«-Skriptdateien nur ein, wenn Debugging für die Webanwendung aktiv ist.

Visual Studio-Integration

Die Installation der ASP.NET AJAX-Erweiterungen ergänzt Visual Studio um die Projektvorlage »ASP.NET AJAX Enabled Website«. Die Nutzung der Projektvorlage ist ratsam, denn für das Funktionieren von ASP.NET AJAX sind neben einer Referenz auf die Assembly System.Web.Extensions.dll auch umfangreiche Konfigurationseinstellungen notwendig, damit sich die Erweiterungen in die bestehende Infrastruktur integrieren. So muss zum Beispiel der HTTP-Handler für die Dateinamenerweiterung .asmx auf die System.Web.Extensions.dll umgebogen werden, damit die Webservices auch JSON anstelle von SOAP erzeugen.

Leider gibt es noch keinen Assistenten, um die Konfigurationseinstellungen nachträglich in eine Konfigurationsdatei einer bestehenden Webanwendung einzubetten. Hier muss der Webentwickler sorgfältig per Kopieren&Einfügen die notwendigen Einstellungen aus einem der bei der Installation mitgelieferten web.config-Dateien übernehmen – sonst fliegen ihm zahlreiche Fehlermeldungen um die Ohren.

ScriptManager

Das ScriptManager -Serversteuerelement, das Teil der ASP.NET-AJAX-Erweiterungen ist, muss auf jeder Webseite erscheinen, die AJAX verwenden soll. Es ist ein Entwurfszeitsteuerelement und wird in dem Designer nur als grauer Kasten (wie die Datenquellensteuerelemente) dargestellt. Zur Laufzeit sorgt das ScriptManager -Serversteuerelement für die Einbindung der in der Seite benötigten JavaScript-Dateien.

JavaScript-Erweiterungen

Als Teil der Microsoft AJAX Library hat Microsoft die Sprache JavaScript um Konzepte der Objektorientierung (Klassen, Vererbung, Namensräume, Schnittstellen) erweitert. Da die Erweiterungen selbst wieder in JavaScript geschrieben sind, ist weder ein .NET Framework noch ein ActiveX-Steuerelement notwendig und eine Browserunabhängigkeit möglich. Ebenfalls enthalten in der AJAX Library sind Erweiterungen eingebauter JavaScript-Typen wie Object , Array , Number , String , Boolean und Error . Über eine zusätzliche Klassenbibliothek besitzt JavaScript plötzlich auch die selbstanalytischen Fähigkeiten von Reflection. All dies geschieht mit dem Ziel, dem .NET-Entwickler den gewohnten Komfort auch in JavaScript zu bieten.

Partielle Seitenerzeugung

Die einfachste Nutzung der ASP.NET-AJAX-Lösung stellt die partielle Seitenerzeugung (Partial Page Rendering) dar. Dabei tauscht der Browser bei einem Rundgang zum Server nicht die ganze Seite aus, sondern nur ein oder mehrere Seitenfragmente. Die Seitenfragmente erzeugt der Server im Fall des Einsatzes von ASP.NET durch Ausführung von Serversteuerelementen, die HTML erzeugen. Der Webserver erkennt an speziellen Parametern des Aufrufs, dass nicht die ganze Seite neu zu erzeugen ist, sondern nur einzelne Teile. Der Aufwand für den Browser ist minimal: JavaScript muss nur den Inhalt einer wohl definierten Region im Document Object Model (DOM) der Webseite durch das neue Fragment ersetzen.

UpdatePanel

Programmieraufwand für die partielle Seitenerzeugung entsteht weder auf dem Client noch auf dem Server: Microsoft hat sowohl das notwendige JavaScript implementiert als auch die notwendigen Anpassungen von ASP.NET bereits vorgenommen. Der Webentwickler muss der Webseite nur zwei Serversteuerelemente hinzufügen: ein ScriptManager -Steuerelement, das die notwendigen Client-Skripte in die Seite einbindet, und ein (oder mehrere) UpdatePanel -Steuerelement(e), das die zu aktualisierenden Seitenfragmente aufspannt. Ein UpdatePanel -Steuerelement bietet selbst keine visuelle Darstellung, sondern grenzt nur statische und dynamische Seitenbereiche voneinander ab. Es kann pro Seite beliebig viele und auch verschachtelte UpdatePanel -Steuerelemente geben.

Aktualisierungseinstellungen

Per Voreinstellung führt ein Klick auf eine Schaltfläche oder einen Hyperlink in einem UpdatePanel -Steuerelement zu einem AJAX-Aufruf des Webservers, bei dem ASP.NET den UpdatePanel -Inhalt serverseitig neu erzeugt.

Bei komplexeren Abhängigkeiten zwischen Steuerelementen und zu aktualisierenden Seitenfragmenten kann auch expliziter Programmcode die Aktualisierung einzelner Seitenteile anstoßen, indem man serverseitig die Methode Update() auf dem UpdatePanel -Steuerelement aufruft. Auch clientseitig kann man Code hinzufügen, der zu Beginn oder am Ende eines AJAX-Rückrufs ausgeführt wird.

Mit dem Attribut UpdateMode im UpdatePanel -Steuerelement legt man fest, wann das Seitenfragment aktualisiert wird:

§     UpdateMode="Always" : Wird immer beim Rückruf aktualisiert. Dies ist die Standardeinstellung.

§     UpdateMode="Conditional" : Wird nur fallweise aktualisiert, abhängig vom definierten Trigger (siehe nächster Abschnitt) oder vom manuellen Aufruf der Update() -Methode.

 

    TIPP          Mit ChildrenAsTriggers = "false" legt man fest, dass untergeordnete Steuerelemente bei einem Rückruf nicht automatisch das Seitenfragment aktualisieren.

 

Beispiel

Möchte man zum Beispiel erreichen, dass beim Blättern in einem GridView -Steuerelement nicht jedes Mal die ganze umgebende Seite neu geladen wird, muss der Entwickler nichts anderes tun, als das GridView -Steuerelement in das UpdatePanel -Steuerelement einzubetten. Fortan kann der Endbenutzer ohne Flackern und ohne Veränderung der Scroll-Position des Browser-Fensters im Datenbestand stöbern.

<asp:ScriptManager ID="SM1" runat="server" AutoPostBack="True">
</asp:ScriptManager>

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
  <ContentTemplate>
   Filter nach Abflugort:
   <asp:DropDownList ID="C_Ort" runat="server"

   </asp:DropDownList>
   <asp:GridView ID="C_Fluege" runat="server"

   </asp:GridView>
  </ContentTemplate>

  <asp:DropDownList ID="C_Seitengroesse" runat="server" AutoPostBack="True"

 </asp:DropDownList>
 </asp:UpdatePanel>

Listing 21.1    Einsatz des UpdatePanel-Steuerelements

Abbildung 21.2    
ScriptManager, UpdatePanel
und UpdateProgress im Webdesigner

Abbildung 21.3    Lösung mit partieller Seitenerzeugung

UpdateProgress

Mit einem UpdateProgress -Steuerelement kann der Entwickler ergänzend zu einem UpdatePanel -Steuerelement definieren, dass während der Aktualisierung eines Seitenfragments der Endbenutzer eine bestimmte Anzeige, z. B. ein animierte GIF-Grafik, sehen soll. Außerdem kann man definieren, dass der Endbenutzer die Aktion über eine Schaltfläche oder einen Link abbrechen kann. Dazu muss man clientseitig abortPostBack() aufrufen, siehe nächstes Beispiel.

 

  HINWEIS        Ein UpdateProgress -Steuerelement wird bei jedem AJAX-Rückruf durch irgendein UpdatePanel -Steuerelement auf der Seite angezeigt. Die Anzeige kann aber auf ein bestimmtes UpdatePanel -Element reduziert werden.

 

Beispiel

In dem vorherigen Beispiel war in der Ergebnisseite bereits eine Fortschrittsanzeige enthalten. Hier folgt der dafür notwendige XML-Code.

Einsatz des UpdateProgress-Steuerelements

Trigger

Alle Steuerelemente, die innerhalb eines UpdatePanel -Steuerelements liegen und einen Rückruf zum Server auslösen (weil sie entweder eine Schaltfläche oder mit AutoPostback="True" versehen sind), lösen eine Aktualisierung des Inhalts des UpdatePanel -Steuerelements aus. Auch ein anderes (außen liegendes) Seitenelement oder ein Timer können eine Aktualisierung anstoßen. Dafür muss der Webentwickler dem UpdatePanel -Steuerelement einen Trigger zuordnen. Die Maßeinheit beim Trigger sind Millisekunden (Standardwert 60.000, also einmal pro Minute).

Beispiel

Das folgende Listing sorgt dafür, dass das Steuerelement »C_Ort«, das nicht im UpdatePanel -Inhalt liegt, eine Aktualisierung des UpdatePanel -Inhalts anstößt, wenn das Ereignis SelectedIndexChanged() ausgelöst wird.

<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
  <Triggers>
   <asp:AsyncPostBackTrigger ControlID="C_Ort" EventName="SelectedIndexChanged" />
  </Triggers>

</asp:UpdatePanel>

Listing 21 .3    Trigger beim UpdatePanel

Timer

Ein Timer -Steuerelement ist ein Serversteuerelement, das JavaScript zum Browser sendet, mit dem in einem periodischen Intervall ein Skript gestartet werden kann oder mit dem ein UpdatePanel -Steuerelement aktualisiert werden kann.

Beispiel

Die folgende Abbildung zeigt eine Fortschrittsanzeige, die serverseitig auf Basis des tatsächlichen Arbeitsfortschritts einer lang anhaltenden Aktion in einem Hintergrund-Thread entsteht. Die Fortschrittsanzeige basiert auch auf der partiellen Seitenerzeugung. Der Browser fragt durch einen Timer einmal pro Sekunde nach dem aktuellen Seitenfragment für die Fortschrittsanzeige. Die Verbindung eines UpdatePanel -Steuerelements mit einem Timer-Steuerelement sorgt für das periodische Aktualisieren des Seitenteils.

Abbildung 21 .4    Fortschrittsanzeige auf Basis eines
UpdatePanel-Steuerelements

<asp:ScriptManager ID="C_SM" runat="server" />
<asp:Timer ID="C_Timer" runat="server" Enabled="true" Interval="1000">
</asp:Timer>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
 <ContentTemplate>
  <asp:Literal ID="C_Refresh" runat="server"></asp:Literal>
  Fortschritt:
  <asp:Label ID="C_Fortschritt" runat="server" Text="Label"></asp:Label>
  <div style="background-color: black; height: 1px; width: 400px">
  </div>
  <asp:Literal ID="C_Balken" runat="server">
 <div style="background-color:red;height:10px;width:400px"></div>
  </asp:Literal>
  <div style="background-color: black; height: 1px; width: 400px">
  </div>
 </ContentTemplate>
 <Triggers>
  <asp:AsyncPostBackTrigger ControlID="C_Timer" />
 </Triggers>
</asp:UpdatePanel>

Listing 21.4    Timer, Trigger und UpdatePanel

Webservice-Aufrufe

An dem vorherigen Beispiel der Fortschrittsanzeige wird deutlich, dass auch bei der partiellen Seitenerzeugung der Overhead immer noch groß sein kann: Jedes Mal sendet der Server die im Panel enthaltenen HTML-Tags zur Erzeugung der Balken zum Browser. Eigentlich braucht der Browser aber nur eine einzige Zahl, aus der er die Darstellung selbst erzeugen könnte. ASP.NET AJAX bietet daher ein zweites Verfahren an, bei dem einzelne elementare Daten oder auch komplexere Datenstrukturen ohne die Layout-Information im Stil eines Remote Procedure Call (RPC) zum Browser übermittelt werden. Auf der Serverseite definiert der Entwickler eine .NET-Methode mit Parametern und Rückgabewert. Der Client erhält über einen generierten Proxy die Möglichkeit, diese Methode wie jede andere JavaScript-Methode aus JavaScript heraus aufzurufen. Die dem Methodenaufruf zugrunde liegende Verwendung des XmlHttpRequest -Objekts verbirgt der Proxy ebenso vor dem Benutzer wie die browserspezifischen Eigenarten dieses Objekts.

Das Interessante an den Browser-Rückrufen ist, dass Microsoft auf einem Konzept aufsetzt, welches .NET sowieso schon seit Version 1.0 bietet: ASP.NET-basierte Webservices (ASMX). Ein mit ASP.NET erzeugter XML-Webservice tauscht normalerweise SOAP-Nachrichten aus und stellt die Metadaten als WSDL-Dokument bereit. Für die AJAX Library hat Microsoft sich aber für ein Verfahren entschieden, das dem Browser die Last der Auswertung von XML-Dokumenten abnimmt. Wenn der Entwickler einen XML-Webservice zusätzlich mit der Annotation [ScriptService ] ausstattet, erzeugt der Webservice durch Anhängen von »/js« an den URL plötzlich JavaScript-Code für einen Browser statt WSDL und serialisiert statt in SOAP-Format in Form der JavaScript Object Notation (JSON). Diesen Ablauf veranschaulicht die folgende Abbildung.

Abbildung 21.5    AJAX-Aufrufe von ASMX-Webservices

Der auch in diesem Fall notwendige ScriptManager erhält den URL des Webservice. Visual Studio lässt die Wahl, ob der von dem Webservice erzeugte JavaScript-Proxy-Code jeweils ad hoc von dem Webservice abgerufen oder in die Webseite eingebettet werden soll. Auf den Webservice kann man dann aus einer beliebigen JavaScript-Routine über den Namen der Klasse und der Methode zugreifen.

Dabei hat die JavaScript-Methode aber immer zwei Parameter mehr als die ursprüngliche Methode. Die zusätzlichen beiden Parameter erfüllen das »A« in AJAX, die Asynchronität. Der Aufrufer erhält keinen Rückgabewert von dem Methodenaufruf, sondern gibt zwei JavaScript-Routinen an, die im Erfolgs- bzw. Fehlerfall aufzurufen sind.

 

  ACHTUNG        WCF-Dienste können in der ASP.NET AJAX Version 1.0 noch nicht verwendet werden. Dies will Microsoft aber in der nächsten Version von ASP.NET AJAX ergänzen. Zu beachten ist ferner, dass man immer nur Webservices auf dem gleichen Webserver aufrufen kann, auf dem auch die Webseite liegt. Dies ist eine Sicherheitsfunktion des XmlHttpRequest -Objekts. Zum Aufruf von Webservices auf anderen Webservern (z. B. für Mashups) muss der Webentwickler einen lokalen Wrapper erstellen. In der zukünftigen ASP.NET AJAX Version 2.0 will Microsoft dies durch deklarierbare Webservices-Bridges vereinfachen.

 

Beispiel

In dem folgenden Beispiel werden drei AJAX-Webservice-Aufrufe verwendet:

§     Flugnummernsuche: Beim Klick auf die »Prüfen«-Schaltfläche werden Informationen zu dem in das Textfeld eingegebenen Flug abgeholt.

§     Abflugortauswahl: Bei der Auswahl eines Abflugortes wird die Liste der erreichbaren Zielorte geholt.

§     Zielauswahl: Bei der Auswahl eines Zielortes wird der nächste verfügbare Flug angezeigt.

Abbildung 21.6    Beispiel, in dem ASP.NET AJAX-Webservice-Aufrufe verwendet werden

Das folgende Listing zeigt einen mit [ScriptMethod] annotierten ASMX-Webservice (in Ausschnitten), der im Hintergrund der Lösung arbeitet. Durch nur eine einzige zusätzliche Codezeile wird aus einem ASMX-Webservice ein Endpunkt für AJAX-Aufrufe des Webbrowsers.

WebService(Namespace="http://IT-Visions.de/wwwings", Name="WorldWideWings Flugplan-Webservice", Description="Webservices für den WorldWideWings-Flugplan!"), WebServiceBinding(ConformsTo=WsiProfiles.BasicProfile1_1, EmitConformanceClaims=true)]
[System.Web.Script.Services.ScriptService()]
public class WWWingsFlugplanService : System.Web.Services.WebService
{
 [WebMethod()]
 public de.WWWings.Flug GetFlight(long FlightNo)
 {
  return de.WWWings.FlugBLManager.HoleFlug(FlightNo);
 }

}

Listing 21.5    Einsatz von [ScriptService]

 

Bei einem solchen Webservice-Aufruf geht es auch auf dem Client nicht ohne eigenen Programmcode, denn der Entwickler muss festlegen, welches Seitenelement die Aktion auslöst, woher die Parameter kommen und vor allem wie das Ergebnis in der Seite darzustellen ist. Hier vermisst man noch von der serverseitigen Programmierung gewohnte IntelliSense-Eingabeunterstützung mit Befehlsvervollständigung und einen guten Debugger. Visual Studio 2005 liefert zwar einen JavaScript-Debugger mit; dieser ist aber umständlich. Eine bessere Unterstützung für AJAX-Entwickler verspricht Microsoft mit der nächsten Version von Visual Studio.

In dem folgenden Listung sieht man anschaulich, dass das von dem JavaScript-Proxy gelieferte Ergebnis des AJAX-Aufrufs keine Sammlung von Einzelwerten, sondern ein JavaScript-Objekt mit der gleichen Struktur wie das serverseitige .NET-Objekt Flug ist, also Attribute FlugNr , AbflugOrt , ZielOrt etc. besitzt.

<!--- Client-Skript --->

 <script type="text/javascript"> 
            function PageMethodCall()
            {
         
                var testString = "PageMethodCall";
                PageMethods.EchoString(testString, OnSucceeded);
            }
           
            // This is the callback function
            // that process the page method call
            // return value.
           
function OnSucceeded(result)
            {
                // Display the result.
                var RsltElem = document.getElementById("Results");
                RsltElem.innerHTML = result;
            }
 </script>

 <script type="text/javascript" language="javascript">
// ---------------------------------------------------------------
// Hilfsroutinen
// ---------------------------------------------------------------

// Wird aufgerufen, wenn es auf dem Server zu einem Fehler kam
function Fehler( error  )
{
    alert("Fehler bei der AJAX-Verarbeitung auf dem Server: " + error.get_message());
}

// ---------------------------------------------------------------
// Ereignisbehandlung für Flugnummernsuche
// ---------------------------------------------------------------
// Ereignisbehandlung für Flugnummerneingabe
function FlugNachNummerSuchen()
{
//debug.fail("test");
document.all.C_Ergebnis1.innerHTML = "Ihre Eingabe wird geprüft...";
// Flugnummer auslesen
var FlugNr = document.forms[0].C_FlugNr.value;

// AJAX-Aufruf gegen ASMX-Webservice
WWWingsFlugplanService.GetFlight(FlugNr,FlugNachNummerSuchen_Ergebnis,Fehler);
// AJAX-Aufruf gegen Seitenmethode

//PageMethods.HoleFlug(n,FlugNachNummerSuchen_Ergebnis, Fehler);
}

// Rückruf
function FlugNachNummerSuchen_Ergebnis(result)
{
 document.all.C_Link.href="ajax/Fortschrittsanzeige_ATLAS.aspx?id=" + result.FlugNr;
 ausgabe = "Sie haben gewählt:<br>Flug " + result.FlugNr + " von " + result.AbflugOrt + " nach " + result.ZielOrt + " und hat " + result.FreiePlaetze + " freie Plätze!";
 document.all.C_Ergebnis1.innerHTML = ausgabe;
 document.all.C_Link.style.visibility ="visible"
 }

// ---------------------------------------------------------------
// Ereignisbehandlung für Abflugauswahl
// ---------------------------------------------------------------
function AbflugortAuswahl() {
C_Abflugort = $get('<%= this.C_Abflug.ClientID %>');
//alert("OK");
// Ermittlung der Option
var abflug = C_Abflugort.options[C_Abflugort.selectedIndex].value;
// Callback zum Server
document.all.C_Ergebnis2.innerHTML = "Lade Zielorte...";
WWWingsFlugplanService.GetDestinations(abflug,AbflugortAuswahl_Ergebnis);
}

// Rückruf
function AbflugortAuswahl_Ergebnis(result)
{
 C_Zielort = document.getElementById('<%= this.C_Zielort.ClientID %>');
 document.all.C_Ergebnis2.innerHTML = result.length + " Zielorte wurden gefunden.";
 // Leeren der Liste
 while (C_Zielort.options.length > 0) { C_Zielort.remove(0); }
 // Fuellen der Liste
 for (var i=0; i<result.length; i++) {

 //C_Zielort.visible = true;
 var Option = document.createElement("option");
 Option.value = result[i];
 Option.text = result[i];
 C_Zielort.add(Option);
 }
}
// ---------------------------------------------------------------
// Ereignisbehandlung für Zielauswahl
// ---------------------------------------------------------------
// Ereignisbehandlung für Zielortauswahl
function ZielortAuswahl() {
C_Abflugort = document.getElementById('<% = this.C_Abflug.ClientID %>');
C_Zielort = document.getElementById('<%= this.C_Zielort.ClientID %>');
// Ermittlung der Option
var abflugort = C_Abflugort.options[C_Abflugort.selectedIndex].value;

var zielort = C_Zielort.options[C_Zielort.selectedIndex].value;
ausgabe = "Sie haben gewählt:<br>Route von " + abflugort + " nach " + zielort;
 document.all.C_Ergebnis1.innerHTML = ausgabe;

document.all.C_Link.href="ajax/Fortschrittsanzeige_ATLAS.aspx?von=" + abflugort +"&nach=" + zielort;
 document.all.C_Link.style.visibility ="visible"
}
 </script>

Listing 21 .6    Das clientseitige Skript für das Beispiel

Bei dem AJAX-Aufruf eines ASMX-Webservice sind die HTTP-Header größer als die eigentliche Nutzlast, wie man im Netzwerkmonitor Fiddler [FID01] (siehe folgende Abbildung) erkennt.

Abbildung 21.7    Ein AJAX-Webservice-Aufruf mit einem HTTP-Monitor betrachtet

 

    TIPP          Neben der Möglichkeit zum Aufruf von Webservices, die in eigenständigen ASMX-Dateien realisiert sind, kann der AJAX-Entwickler auch die Option nutzen, Methoden in einer normalen ASPX-Seite via AJAX aufzurufen: Dazu muss die Methode mit [WebMethod] annotiert sein (im Widerspruch zu [ScriptService] bei .asmx-Dateien) und dann im Browser über den feststehenden Objektnamen PageMethods angesprochen werden.

Als vordefinierte Webservices stellt ASP.NET AJAX die Authentifizierung und den Personalisierungsdienst von ASP.NET zur Verfügung. Somit kann der Webentwickler den Anmeldedialog und Personalisierung von Webseiten durch AJAX realisieren.

 

Extender

Ein Extender ist in der Sprache von ASP.NET AJAX eine Erweiterung, die ein bestehendes (»dummes«) HTML-Steuerelement um zusätzliche Funktionen erweitert. Ein Extender besitzt immer eine clientseitige Komponente in JavaScript; eine serverseitige Komponente ist optional.

Das AJAX Control Toolkit enthält zahlreiche Extender und darauf basierende Client-Steuerelemente (allgemein DHTML-Widgets genannt).

Beispiele für diese Steuerelemente sind:

§     Das Accordion -Steuerelement, das Bereiche in einer kleinen Animation auf- und zuklappt, arbeitet rein clientseitig. Allerdings wurde sowohl das auf dem Client notwendige HTML als auch das zugehörige JavaScript auf dem Server erzeugt.

§     Mit dem ReorderList -Steuerelement kann ein Endbenutzer rein clientseitig den Inhalt und die Sortierung einer Liste bestimmen.

§     Das CascadingDropDown -Steuerelement fragt nach der Auswahl in einem Feld beim Webserver nach, welche Daten in das nächste Auswahlfeld gehören.

Zusammen mit dem AJAX Control Toolkit liefert Microsoft auch eine Sammlung von Beispielen, die jedes einzelne Steuerelement in Aktion zeigen (siehe Abbildung).

Abbildung 21.8    Steuerelemente im AJAX Control Toolkit

 

  ACHTUNG        Das Control Toolkit ist kein klassisches Microsoft-Produkt, sondern Microsoft bezeichnet es als »Gemeinsames Projekt von Microsoft und der .NET Community«, das im Rahmen des Projektportals Codeplex zur Verfügung steht. Jedermann hat die Möglichkeit, sich für eine Mitarbeit bei dem Projekt zu bewerben. Zumindest die zum Redaktionsschluss verfügbare Version weist noch deutliche Fehler auf, insbesondere im Zusammenspiel mehrerer Extender auf einer Seite (siehe dazu [HS06]).

 

Ausblick

Zukünftig wird man in ASP.NET AJAX noch mehr Steuerelemente sehen, die primär auf dem Client arbeiten. In den ursprünglichen Vorabversionen von »Atlas« waren einige Funktionen enthalten, die es in der ASP.NET AJAX 1.0 bzw. dem zugehörigen Control Toolkit nicht gibt. Dort bietet Microsoft für JavaScript die Abstraktion, die der Webentwickler schon von ASP.NET kennt. Zukünftig gibt es neben den Server-Steuerelementen, die ASP.NET in HTML, CSS und JavaScript umwandelt, auch Client-Steuerelemente, die JavaScript in die gleichen Ergebnisformate transformiert. Wie bei den Serversteuerelementen kann man das XML zur Deklaration verwenden: Microsoft spricht daher von XML Script. Microsoft überträgt damit das Abstraktionsmodell von ASP.NET auf den Browser.

Zu den Highlights von XML Script werden eine eigene Animationssprache und die clientseitige Datenbindung gehören. Der Webentwickler hat dann bei überschaubaren Datenmengen die Wahl, die Daten in einem Rutsch zum Browser zu befördern und Suchen, Sortieren und Blättern ohne einen einzigen Roundtrip zum Server zu implementieren.

 

  HINWEIS        Zum Redaktionsschluss dieses Beitrags gibt es bereits eine Vorabversion der künftigen ASP.NET-AJAX-Version unter dem Titel »ASP.NET AJAX Futures«.