Microsoft Ajax
Tobias Hauser
Microsoft Ajax
schnell + kompakt
Tobias Hauser Microsoft Ajax schnell + kompakt ISBN 978-3-939084-31-0
© 2007 entwickler.press, ein Imprint der Software & Support Verlag GmbH
1. Auflage, 2007
http://www.entwickler-press.de/ http://www.software-support.biz/ Ihr Kontakt zum Verlag und Lektorat:
[email protected] Bibliografische Information Der Deutschen Bibliothek Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.ddb.de abrufbar.
Korrektorat: Petra Kienle Satz: text & form GbR, Carsten Kienle Umschlaggestaltung: Caroline Butz Belichtung, Druck und Bindung: M.P. Media-Print Informationstechnologie GmbH, Paderborn. Alle Rechte, auch für Übersetzungen, sind vorbehalten. Reproduktion jeglicher Art (Fotokopie, Nachdruck, Mikrofilm, Erfassung auf elektronischen Datenträgern oder andere Verfahren) nur mit schriftlicher Genehmigung des Verlags. Jegliche Haftung für die Richtigkeit des gesamten Werks kann, trotz sorgfältiger Prüfung durch Autor und Verlag, nicht übernommen werden. Die im Buch genannten Produkte, Warenzeichen und Firmennamen sind in der Regel durch deren Inhaber geschützt.
Inhaltsverzeichnis Vorwort
7
Kapitel 1: Grundlagen 1.1 Bestandteile 1.2 Einrichtung
9 11 12
Kapitel 2: UpdatePanel und Co. 2.1 UpdatePanel Trigger Attribute 2.2 UpdateProgress 2.3 Timer 2.4 Clientseitige Steuerung 2.5 ScriptManager und Co. 2.6 Skripte einbinden 2.7 Verschachtelte Sites 2.8 Programmieransätze 2.9 Fehlerhandling
17 18 21 25 25 27 30 33 33 34 35 37
Kapitel 3: JavaScript-API 3.1 pageLoad() 3.2 $get() 3.3 Event-Handler 3.4 Elemente DomElement Komponenten, Controls und Behavior 3.5 Erweiterte JavaScript-Objekte 3.6 StringBuilder
39 40 40 41 44 45 46 47 50
schnell + kompakt
5
Inhaltsverzeichnis
Kapitel 4: Web Services und Co. 4.1 Web Services Web Service einrichten Web Service aufrufen Fehlerhandling Datenaustausch 4.2 Forms Authentication Services Serverseitig Clientseitig 4.3 Profile Services Serverseitig Clientseitig
53 53 54 57 61 62 66 66 68 75 76 77
Kapitel 5: Control Toolkit 5.1 Eigenständige Controls 5.2 Extender Formulare und Informationen Modale Fenster Effekte
81 86 89 89 93 95
Kapitel 6: Futures und Sonstiges 6.1 XML-Script 6.2 Drag&Drop 6.3 Animationen
99 101 103 112
Stichwortverzeichnis
115
6
Vorwort Noch ein Ajax-Framework? Als Microsoft sein Ajax-Framework, damals noch unter dem Namen Atlas ankündigte, gab es schon eine Menge Frameworks auf dem Markt. Und während Microsoft noch entwickelte, wurden es immer mehr. Warum also sollte man auf die Lösung von Microsoft setzen? Zum einen gibt es für ASP.NET nicht so viele Alternativen. Außerdem garantiert Microsofts Engagement die Weiterentwicklung und man hält sich an die Standardlösung für ASP.NET. Zu guter Letzt soll noch ein subjektives Argument folgen: Microsoft ASP.NET Ajax ist zwar bei weitem noch nicht perfekt, enthält aber eine Unmenge an Funktionen und ist auf dem Weg, ein wirklich gutes Ajax-Framework zu werden. Dieses Buch möchte Ihnen dabei helfen, Microsoft ASP.NET Ajax zu verstehen und einzusetzen. Dazu werden alle wichtigen Möglichkeiten des Framework näher beleuchtet und anhand von Beispielen erklärt. Im Einzelnen ist Folgendes enthalten: 쐌 Kapitel 1 erläutert die Bestandteile von Microsoft ASP.NET Ajax. 쐌 Kapitel 2 zeigt die grundlegenden Möglichkeiten, um nur Teile einer Seite zu aktualisieren. Im Vordergrund stehen das UpdatePanel und die wichtigen Helfer. 쐌 Kapitel 3 stellt die JavaScript-API von Microsoft ASP.NET Ajax vor. Seien es einfacher formatierbare Datumswerte, schnellerer DOM-Zugriff oder Event-Handler, Microsoft bietet viel Nützliches für den Alltag. 쐌 Kapitel 4 kümmert sich um den Zugriff auf Web Services. Sie sind ein einfacher und schneller Weg, um per Microsoft ASP.NET Ajax Daten auszutauschen. Außerdem werden die
schnell + kompakt
7
Vorwort
Dienste zur Nutzerauthentifizierung und Personalisierung behandelt. 쐌 Kapitel 5 beschreibt die nützlichen Steuerelemente aus dem Control Toolkit. Sie lernen Animationen, Register und Formularhelfer kennen. 쐌 Kapitel 6 beleuchtet die Ajax-Erweiterungen in den Microsoft ASP.NET Futures. Themen sind unter anderem Drag&Drop und Animationen. Die Beispiele zum Buch stehen Ihnen unter http://www.hauserwenz.de/support/ zur Verfügung. Dort finden Sie außerdem Errata und Updates zum Buch. In unserem Weblog unter http:// www.hauser-wenz.de/blog/ gibt es regelmäßig neue Einträge zu den aktuellen Themen der Webentwicklung, darunter natürlich auch Microsoft ASP.NET Ajax. Für Anregungen und Kritik zum Buch oder zur von Christian Wenz und mir mitgestalteten Buchreihe schnell + kompakt finden Sie unter http://www.hauser-wenz.de/ support/kontakt/ ein entsprechendes Formular. Auch Fragen zum Buch sind selbstverständlich willkommen und werden möglichst zeitnah beantwortet. Aus Fairness gegenüber den zahlenden Kunden kann ich leider keine Fragen abseits des Buchinhalts kostenlos beantworten. Auch dieses Buch wäre ohne Hilfe nicht möglich gewesen. Christian sei für sein Feedback, seine Anregungen und seine Unterstützung gedankt, Christiane und Erik für ihr Engagement. Viel Spaß mit Microsoft ASP.NET Ajax! Tobias Hauser Im Mai 2007
8
KAPITEL 1 Grundlagen 1.1
Bestandteile
11
1.2
Einrichtung
12
Ajax ist in aller Munde. Aber das Entwickeln von Ajax-Anwendungen ist nicht gerade trivial. Eine Hürde ist der Einsatz von JavaScript mit allen Browser-Abhängigkeiten und Schwierigkeiten, die eine interpretierte Skriptsprache so mit sich bringt. Dementsprechend sprießen an allen Ecken und Enden die Frameworks und Bibliotheken, die die Arbeit erleichtern. Man kann dabei grob Bibliotheken unterscheiden, die auf JavaScript basieren, und solche, die eng mit einer serverseitigen Technologie verbunden sind. Für die hauseigene serverseitige Technologie ASP.NET will Microsoft selbst das Standardrahmenwerk schaffen. Nach langer Vorbereitungszeit unter dem Codenamen Atlas gibt es jetzt Microsoft ASP.NET 2.0 Ajax. Das Framework besteht sowohl aus serverseitigen als auch aus clientseitigen Teilen. Es hat in relativ kurzer Zeit unter den ASP.NET-Entwicklern große Verbreitung gefunden und gilt schon jetzt als Quasistandard. Einige prominente Beispielprojekte wie http://www.pageflakes.com/ setzen trotz der durchaus noch vorhandenen Kinderkrankheiten auf Microsoft ASP.NET 2.0 Ajax. Und auch das bekannte auf ASP.NET basierende Open Source CMS DotNetNuke integriert mittlerweile das Ajax-Framework.
schnell + kompakt
9
1 – Grundlagen
Hinweis Eine Alternative zu Microsoft ASP.NET Ajax soll nicht verschwiegen werden: Ajax.NET Professional von Michael Schwarz (http://www.ajaxpro.info/) bietet ein klassisches Ajax-Rahmenwerk. Die zentrale Anlaufstelle für das Ajax-Framework ist http:// ajax.asp.net/. Dort finden Sie alle Bestandteile, Dokumentation, Beispiele und Aktuelles.
Abb. 1.1: Auf der Ajax-Homepage finden Sie alle Dateien und Informationen
10
Bestandteile
1.1 Bestandteile Microsoft ASP.NET 2.0 Ajax ist kein integriertes Framework an sich, sondern besteht aus verschiedenen Teilen, die auch alle einzeln zur Verfügung stehen: 쐌 ASP.NET 2.0 Ajax Extensions 1.0 ist der zentrale Teil. Er besteht aus den grundlegenden Funktionen und den AjaxTemplates für die Entwicklungsumgebung Visual Studio und Visual Web Developer. Die grundlegenden Funktionen lassen sich grob in serverseitige Controls (UpdatePanel etc.), in Dienste (Web Services, Profile Services etc.) und in clientseitige Objekte unterteilen. Entsprechende Themen, die die Extensions betreffen, finden Sie in Kapitel 2, 3 und 4. 쐌 ASP.NET Ajax Control Toolkit enthält Steuerelemente wie Schieberegler, modale Popups und vieles mehr. Die Entwicklung obliegt allerdings einem Community-orientierten Ansatz unter Microsoft-Kontrolle. Das heißt auch, dass sich im Control Toolkit viele Änderungen ergeben. Erläuterungen zum Control Toolkit finden Sie in Kapitel 5. 쐌 ASP.NET Ajax Futures enthält noch in der Entwicklung befindliche Funktionen und eine eigene Vorlage für auf der CTP basierende Websites in Visual Studio und Visual Web Developer. Es wurde mittlerweile (Stand Mai 2007) mit neuen Funktionen für ASP.NET kombiniert. Unter den Ajax-Funktionen sind schon gut nutzbare Drag&Drop-Funktionen. Da sich die Futures jederzeit ändern kann, finden Sie nur eine kurze Schilderung in Kapitel 6. Von allen drei integralen Bestandteilen steht auch der Quellcode zur Verfügung. Für die Extensions gibt es eine eigene Version des Quellcodes, für das Control Toolkit wählen Sie beim Download aus der Version mit und ohne Quellcode. Bei der Futures ist der JavaScript-Quellcode mit dabei. Allerdings ist die Quellcode-
schnell + kompakt
11
1 – Grundlagen
Version hier mit debug benannt, da sie Formatierungen und Zeilenumbrüche enthält. Hinweis Von den JavaScript-Bestandteilen gibt es sogar eine eigene, von ASP.NET unabhängige Version namens Microsoft Ajax Library. Sie lässt sich beispielsweise auch in andere Technologien integrieren. Außerdem gibt es natürlich eine Dokumentation. Die zentrale Dokumentation auf der Website (http://ajax.asp.net/docs/) dreht sich um die clientseitigen und serverseitigen Fähigkeiten der ASP.NET 2.0 Ajax Extensions 1.0. Sie ist herunterladbar oder auch online einsetzbar. Daneben gibt es auf der Website noch Beispiele und Videotutorials. Das ASP.NET Ajax Control Toolkit wird dagegen mit einer eigenen Dokumentation ausgeliefert, die gleich mit entsprechenden Beispielen der Steuerelemente verbunden ist. Und für die ASP.NET Ajax Futures ist Dokumentation im Moment noch Mangelware. In der Tat ist es teilweise sogar schwierig, weil im Web zu einigen Funktionen wie Drag&Drop noch auf früheren Atlas-Versionen basierende Beispiele grassieren. Hier hilft oft nur ein Blick in den Quellcode.
1.2 Einrichtung Sehr empfehlenswert und in der Praxis auch fast unumgänglich ist der Einsatz einer Entwicklungsumgebung. Hier gibt es verschiedene Möglichkeiten: Microsoft selbst bietet die professionelle Entwicklungsumgebung Visual Studio in verschiedenen Versionen. Für Ajax ist jede Version geeignet. Eine kostenfreie Alternative von Microsoft ist Visual Web Developer Express
12
Einrichtung
(http://www.microsoft.com/germany/msdn/vstudio/products/express/ vwd/default.mspx). Dieser Editor bietet die meisten der ASP.NETFunktionen von Visual Studio und besitzt dieselbe Oberfläche. Wer nicht zu einem Microsoft-Produkt greifen möchte, wird bei SharpDevelop fündig (http://www.icsharpcode.net/OpenSource/SD/ Default.aspx). Hinweis In diesem Buch kommt Visual Web Developer Express zum Einsatz. Die Erläuterungen gelten allerdings genauso für Visual Studio. Für einige Funktionen wie die Erweiterung von Controls ist sogar Visual Studio notwendig. Sie sollten Visual Web Developer installieren, bevor Sie die Installation von ASP.NET 2.0 Ajax Extensions 1.0 beginnen. Das benötigte .NET Framework 2.0 wird, falls noch nicht vorhanden, bei dieser Installation mit eingerichtet. Die ASP.NET 2.0 Ajax Extensions 1.0 sind schnell installiert. Laden Sie das msi-Installer-Paket herunter und starten Sie dann per Doppelklick die Installation. Sie müssen nur noch die Lizenz bestätigen, dann läuft die Installation durch. Installiert wird standardmäßig in C:\Programme\Microsoft ASP.NET\ASP.NET 2.0 Ajax Extensions. In das übergeordnete Microsoft ASP.NET-Verzeichnis wird später auch die CTP installiert. In Visual Studio und Visual Web Developer integrieren sich die Ajax Extensions an zwei Stellen: 쐌 Zum einen gibt es eine Vorlage für neue Websites. Sie können nun also eine Ajax-Anwendung erzeugen. Sie enthält gegenüber einer normalen Website schon eine Datei, die den sogenannten ScriptManager integriert. Jede Microsoft Ajax-Webseite benötigt einen ScriptManager. Mehr dazu im nächsten Kapitel.
schnell + kompakt
13
1 – Grundlagen
쐌 Zum anderen sind in der Toolbox bereits serverseitige AjaxControls verfügbar. Auch dazu mehr im nächsten Kapitel.
Abb. 1.2: Eine neue Vorlage für eine Website mit Ajax Extension
Das ASP.NET Ajax Control Toolkit wird etwas anders installiert. Es kommt als ZIP-Archiv daher. Sie müssen es nun an einen beliebigen Ort entpacken. Es wird auf CodePlex in zwei Varianten angeboten: mit und ohne Quellcode. Die Variante mit Quellcode benötigen Sie, wenn Sie sich ansehen wollen, wie die Controls entwickelt werden, und wenn Sie eigene entwickeln wollen. Sie ist auf jeden Fall zu empfehlen. Zentrales Element des ZIPArchivs ist ein Visual-Studio-Projekt (AjaxControlToolkit.sln). Wenn Sie es öffnen und das Projekt ausführen, sehen Sie alle Steuerelemente und auch den Quellcode. Die ASP.NET Ajax Futures wurde mittlerweile (Stand Mai 2007) in die ASP.NET Futures integriert. Sie ist wie die Extensions ein .msi-Installationspaket. Sie installieren sie durch Doppelklick.
14
Einrichtung
Anschließend bestätigen Sie die Lizenz. Sie finden das installierte Futures-Paket standardmäßig unter C:\Programme\Microsoft ASP.NET. Außerdem installiert es eine Visual Studio- und Visual Web Developer-Vorlage, die es Ihnen erlaubt, eine neue Ajax CTP-Website anzulegen. Diese Website besitzt neben dem ScriptManager für die Standardseite auch noch die DLL Microsoft.Web.Preview.dll. Sie enthält die eigentlichen JavaScriptDateien des Futures CTP. Zu finden sind die Dateien auch in der Installation unter C:\Programme\Microsoft ASP.NET\ASP.NET Futures May 2007\v1.1.61025\ScriptLibrary\Microsoft.Web.Preview\ 1.1.61025.0. Hinweis Bei den Futures sind dauernde Änderungen an der Tagesordnung. Neben den Pfaden haben sich auch schon die Namensräume und auch der Name der DLL geändert. Es gibt keine Garantie, dass das in Zukunft nicht weiterhin so ist.
schnell + kompakt
15
KAPITEL 2 UpdatePanel und Co. 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9
UpdatePanel UpdateProgress Timer Clientseitige Steuerung ScriptManager und Co. Skripte einbinden Verschachtelte Sites Programmieransätze Fehlerhandling
18 25 27 30 33 33 34 35 37
Das Herzstück von Microsofts Ajax-Framework sind die Extensions. Und darin gibt es wiederum serverseitige und clientseitige Fähigkeiten sowie die Möglichkeit, mit Diensten zwischen Client und Server zu kommunizieren. In diesem Kapitel stehen die serverseitigen ASP.NET Controls im Vordergrund, mit denen Sie eine Ajax-Anwendung erstellen können, ohne sich um JavaScript Sorgen machen zu müssen. Sie finden die Controls unter dem Register AJAX EXTENSIONS in der Toolbox von Visual Web Developer oder Visual Studio. Sollten Sie keine Entwicklungsumgebung einsetzen, verwenden Sie einfach den in diesem Kapitel gezeigten Code. Das zentrale Steuerelement ist der ScriptManager. Sie benötigen ihn bei jedem Einsatz von Microsoft Ajax, egal ob für serverseitige Controls, clientseitige Steuerung, Control Toolkit oder die CTP-Funktionen.
schnell + kompakt
17
2 – UpdatePanel und Co.
Abb. 2.1: Die Controls in der Toolbox
Wenn Sie als neue Website eine ASP.NET Ajax-Enabled Web Site gewählt haben, ist er schon integriert. Wenn nicht bzw. wenn Sie ein neues WebForm hinzufügen, müssen Sie ihn einfügen. Bedenken Sie aber, dass Sie nur einen ScriptManager pro Seite einsetzen dürfen!
Wenn Sie die Seite nun ausführen, sehen Sie noch nichts. Ein Blick in den Quellcode im Browser verrät, dass der ScriptManager bereits einige Skripte integriert.
2.1 UpdatePanel Das UpdatePanel ist das zentrale serverseitige Steuerelement. Es grenzt einen Bereich der Seite ein, der unabhängig vom Rest aktualisiert wird. Für die Aktualisierung kommt im Hintergrund – wenig überraschend – ein Ajax-Aufruf per XMLHttpRequest-Objekt zum Einsatz. Hinweis Microsoft nennt diese Funktionalität auch Partial Page Rendering. Nur ein Teil der Seite wird also aktualisiert. Der Aufruf ist auch ein asynchroner PostBack.
18
UpdatePanel
Client
HTTP-Request
HTML+JavaScript
Seite anfordern
ASPX-Seite
HTTP-Response HTTP-Request über XMLHttpRequest
UpdatePanel
Server
Partielle Updates
UpdatePanel -Inhalte und -Methoden
HTTP-Response
Abb. 2.2: Die Client-Server-Architektur mit UpdatePanel
Um ein UpdatePanel einzusetzen, ziehen Sie es einfach in Ihr Dokument. In das UpdatePanel werden dann die Elemente eingefügt, die neu geladen werden sollen. Für ein erstes Beispiel kommen ein Label-Control und eine Schaltfläche zum Einsatz. Die Elemente, die in das UpdatePanel eingefügt werden, landen im :
Sie sollten noch ein zweites Label-Control außerhalb des UpdatePanel einfügen, damit Sie die teilweise Aktualisierung der Seite auch sehen können. Nun müssen den Label-Controls noch Werte zugewiesen werden. Dies geschieht im Code (hier in der separaten Datei) bei der Methode Page_Load, die beim Laden der Seite ausgeführt wird:
schnell + kompakt
19
2 – UpdatePanel und Co.
protected void Page_Load(object sender, EventArgs e) { Random ran = new System.Random(); Int32 zahl = ran.Next(0, 100000); Label1.Text = zahl.ToString(); Label2.Text = zahl.ToString(); }
Beide Label-Controls erhalten eine gemeinsame Zufallszahl zwischen 0 und 100000 zugewiesen. Das heißt, beim ersten Laden der Seite enthalten beide die gleiche Zufallszahl. Klicken Sie nun aber auf die Schaltfläche, lädt das UpdatePanel nur den Bereich mit dem ersten Label neu und aktualisiert dementsprechend auch die Zufallszahl. In den nächsten Abschnitten lernen Sie noch mehr Möglichkeiten kennen, diese Aktualisierung zu steuern.
Abb. 2.3: Gleich: Beide Label enthalten dieselbe Zufallszahl
20
UpdatePanel
Abb. 2.4: Neu: Das erste Label wurde dank UpdatePanel ohne Neuladen der Seite aktualisiert
Trigger Im ersten Beispiel wurde die Aktualisierung des UpdatePanelInhalts durch den Klick auf die Schaltfläche ausgelöst. ASP.NET erkennt automatisch, dass eine Schaltfläche vorhanden ist, und verwendet diese als Auslöser, als Trigger. Zu verdanken ist das dem Standardwert true für das Attribut ChildrenAsTriggers für das UpdatePanel. Ist ChildrenAsTriggers nicht auf false gesetzt, werden direkte Kindelemente im Inhalt des UpdatePanel automatisch als Auslöser verwendet. Sind mehrere Elemente vorhanden, die potenzielle Auslöser sind, werden alle als Auslöser registriert. Auch Verschachtelungen in andere Steuerelemente, z.B. eine Tabelle, sind möglich. Hinweis UpdatePanel-Elemente lassen sich auch verschachteln. Dabei ist die automatische Erkennung von untergeordneten Auslösern aber nicht mehr möglich. Ein untergeordnetes UpdatePanel wird vielmehr aktualisiert, wenn das übergeordnete aktualisiert wird.
schnell + kompakt
21
2 – UpdatePanel und Co.
In den meisten Fällen ist die automatische Erkennung von Auslösern sinnvoll. Wenn Sie allerdings z.B. aus einem UpdatePanel ein anderes aktualisieren möchten, sollten Sie die Erkennung mit ChildrenAsTriggers deaktivieren. Ist ChildrenAsTriggers auf false gesetzt, muss gleichzeitig das Attribut UpdateMode auf Conditional stehen:
Der UpdateMode gibt an, wann das UpdatePanel aktualisiert wird. Zur Wahl stehen zwei Optionen: 쐌 Always ist der Standardwert. Er gibt an, dass der Inhalt des UpdatePanel bei jedem PostBack aktualisiert wird, also z.B. auch beim Neuladen der Seite oder bei einem asynchronen Neuladen aus einem anderen UpdatePanel. 쐌 Conditional ruft das Neuladen nur auf, wenn das Aktualisieren durch einen Trigger für das UpdatePanel ausgelöst wird (ob explizit angegeben oder direkt im UpdatePanel, spielt dabei keine Rolle) oder per Code über die serverseitige Methode Update() aufgerufen wird. Wenn ChildrenAsTriggers auf false gesetzt wurde oder wenn ein Element als Auslöser verwendet werden soll, das sich nicht oder tiefer verschachtelt im UpdatePanel befindet, müssen und können Sie die Auslöser selbst setzen. Hier ein Beispiel, bei dem sich die Schaltfläche als gewünschter Auslöser außerhalb des UpdatePanel befindet:
22
UpdatePanel
Um einen Auslöser explizit zu setzen, verwenden Sie den Bereich unterhalb des UpdatePanel. Sie können dort Trigger für einen normalen PostBack, sprich für das Neuladen der gesamten Seite, einfügen. Die häufiger benötigte Alternative sind aber Trigger für asynchrone PostBacks. Damit können Sie ein beliebiges Element und ein beliebiges Ereignis angeben, um die Aktualisierung auszulösen. Hier ein Beispiel, das die Schaltfläche Button1 bei Klick als Auslöser verwendet:
Sie können übrigens auch der Schaltfläche selbst noch Befehle mitgeben. Ein Schaltflächenereignis wird angelegt, wenn Sie die Schaltfläche in der Entwurfsansicht von Visual Web Developer bzw. Visual Studio doppelt anklicken. Alternativ können Sie selbst mit dem Attribut OnClick den Funktionsnamen vergeben und die Funktion schreiben. Das folgende Beispiel fügt an die Zufallszahl von Label1 noch einen Text an:
schnell + kompakt
23
2 – UpdatePanel und Co.
protected void Button1_Click(object sender, EventArgs e) { Label1.Text += " Schaltfläche"; }
Dass der Text erst nach der Zufallszahl folgt, zeigt die Ausführreihenfolge (auch Lebenszyklus genannt) der ASP.NET-Seite. Zuerst wird Page_Load() ausgeführt, dann das Klickereignis für die Schaltfläche. Dies gilt nicht nur für „normale“ ASP.NET-Seiten, sondern auch für die Ausführreihenfolge von asynchronen PostBacks per UpdatePanel. Würden Sie auch einen Text für Label2 vergeben, würde dieser nicht angezeigt, da der asynchrone PostBack nur den Bereich des UpdatePanel betrifft.
Abb. 2.5: Ergänzung: Per Schaltflächenklick wird zusätzlicher Text ausgegeben
Hinweis Manche Controls sind nicht mit dem UpdatePanel kombinierbar. Dazu zählt z.B. das Menu-Control. Eine vollständige Liste finden Sie unter http://ajax.asp.net/docs/overview/UpdatePanelOverview.aspx#UpdatePanelCompatibleControls. Teil-
24
UpdateProgress
weise gibt es schon Abhilfen, die den JavaScript-Code von Microsoft Ajax verändern (http://siderite.blogspot.com/2007/ 04/using-menu-inside-updatepanel.html). Als kleine Entschädigung für die Einschränkung ist das UpdatePanel selbst auch mit Masterseiten kombinierbar und in anderen Steuerelementen wie etwa dem GridView einsetzbar.
Attribute Neben den im letzten Abschnitt erläuterten ChildrenAsTriggers und UpdateMode gibt es noch ein paar Attribute für das UpdatePanel. Der RenderMode gibt an, ob das UpdatePanel als Blockelement (sprich ) oder als Inline-Element (sprich ) realisiert wird. Außerdem können Sie das UpdatePanel natürlich auch mit Visible ein- und ausblenden.
2.2 UpdateProgress Ergänzend zum UpdatePanel können Sie den UpdateProgress einsetzen. Dieses Steuerelement zeigt den Fortschritt des Ladevorgangs der Anwendung an. Allerdings sollten Sie sich darunter keine Fortschrittsmeldung mit verlässlichen Prozentangaben vorstellen. Das gibt das allen Ajax-Aufrufen zu Grunde liegende XMLHttpRequest-Objekt nicht her. Vielmehr können Sie mit dem UpdateProgress einfach eine Meldung anzeigen, während die Inhalte geladen werden. Profitipp In Ajax-Anwendungen (z.B. den diversen Webmail-Diensten) gibt es oft animierte Ladeanzeigen mit Ladebalken. Auch dort sind die Informationen nicht genau, sprich, der Nutzer weiß nicht, wie viel Prozent schon geladen wurde oder wie viel noch geladen werden muss. Durch die Animation wird dem
schnell + kompakt
25
2 – UpdatePanel und Co.
Nutzer nur gezeigt, dass etwas passiert. Eine solche Animation können Sie natürlich auch innerhalb des UpdateProgressElements einfügen. Um die Fortschrittsanzeige lokal testen zu können, schicken Sie das Skript in der Page_Load()-Methode für einige Sekunden zum Schlafen: System.Threading.Thread.Sleep(4000);
Die Angabe erfolgt in Millisekunden, sprich, das Skript ruht vier Sekunden. Nun fügen Sie das UpdateProgress-Element in das UpdatePanel ein. Am schnellsten geht das natürlich per Drag&Drop aus der Toolbox. Die Meldung für die Fortschrittsanzeige folgt im : Neue Zufallszahl wird geladen ...
26
Timer
Abb. 2.6: Fortschrittlich: Die Lademeldung erscheint
Das UpdateProgress-Element besitzt selbst noch einige Attribute zur Steuerung: 쐌 AssociatedUpdatePanelID bindet eine Aktualisierungsmeldung an ein UpdatePanel, wenn das UpdateProgress-Element außerhalb des UpdatePanel liegt. 쐌 DisplayAfter verzögert die Ladeanzeige um den angegebenen Wert in Millisekunden (Standard sind 500 Millisekunden, also eine halbe Sekunde), damit der Nutzer nicht sofort eine Lademeldung sieht. 쐌 DynamicLayout gibt an, ob der Platz für die Lademeldung schon reserviert ist (false) oder die Meldung erst eingefügt wird, wenn sie notwendig ist (true). Ersteres wird über die CSSEigenschaft visibility, Letzteres über die CSS-Eigenschaft display realisiert.
2.3 Timer Ein weiteres Control im Standardlieferumfang der Ajax Extensions ist der Timer. Mit ihm lassen sich regelmäßige Aufrufe tätigen – er kapselt insofern die JavaScript-Funktionen setTimeout() und setInterval(). Sie setzen den Timer genauso ein wie eine
schnell + kompakt
27
2 – UpdatePanel und Co.
Schaltfläche. Das heißt, in Verbindung mit einem UpdatePanel fügen Sie ihn entweder im UpdatePanel ein:
Oder Sie setzen ihn außerhalb ein und setzen einen Trigger auf den Timer.
Hinweis Wenn Sie den Timer nicht mit einem UpdatePanel verbinden, führt er automatisch einen PostBack der gesamten Seite durch. Das einzige Attribut, das im Timer gesetzt werden muss, ist das Intervall, in dem der Timer aufgerufen wird. Dies geschieht mit
28
Timer
dem Attribut Interval. Die Angabe erfolgt wie bei den zugrunde liegenden JavaScript-Funktionen in Millisekunden. Ein Wert von 1000 entspricht also einer Sekunde. Profitipp Eine zu schnelle Aktualisierung sorgt nicht nur am eventuell schwachen Client für Performance-Probleme, sondern belastet auch den Server mit sehr vielen Requests. Versuchen Sie, hier ein vernünftiges Maß zu finden und Aktualisierungen zu verbinden. Sie können einen Timer auch für mehrere UpdatePanels verwenden, indem Sie in jedem einen Trigger auf dasselbe Timer-Control einsetzen. In Verbindung mit einem UpdatePanel wird die Aktualisierung übrigens nur durchgeführt, wenn die letzte Abfrage schon beendet ist. Das kann relevant sein, wenn das serverseitige Skript länger braucht und das Intervall sehr kurz gewählt ist. Das Ereignis, das der Timer auslöst, heißt tick. Sie können das z.B. im Trigger verwenden:
Außerdem haben Sie die Möglichkeit, serverseitig darauf zu reagieren.
Sie schreiben nun nur noch eine Methode Timer1_Tick, die bei jeder Aktualisierung – auch in Verbindung mit einem UpdatePanel – aufgerufen wird.
schnell + kompakt
29
2 – UpdatePanel und Co.
2.4 Clientseitige Steuerung Das UpdatePanel lässt sich mit einigen Einschränkungen auch per JavaScript steuern. Das hilft beispielsweise, um dem Nutzer die Möglichkeit zum Abbruch des Update-Prozesses zu geben. Verantwortlich dafür ist die Klasse PageRequestManager. Ein Objekt dieser Klasse erhalten Sie nicht auf üblichem Wege, sondern mit der Methode getInstance(). Das folgende Beispiel zeigt, wie Sie damit einen Aufruf abbrechen. Zuerst benötigen Sie die Schaltflächen. Hier werden sie mit einem UpdateProgress-Element kombiniert, um das Abbrechen plastisch zu zeigen: Neue Zufallszahl wird geladen ...
Die weitere Steuerung erfolgt im JavaScript-Code. Sie müssen prüfen, ob es sich um einen asynchronen Aufruf handelt, und an-
30
Clientseitige Steuerung
schließend mit abortPostback() den Aufruf abbrechen. Dazu erstellen Sie zuerst eine Instanz des PageRequestManager. Dies geschieht hier in der Funktion pageLoad(). Diese Funktion wird von Microsoft Ajax automatisch ausgeführt, nachdem die Seite und alle Skripte geladen sind. Mit add_initializeRequest() wird ein Event-Handler definiert, der bei einer Änderung des Status, sprich einem Request, ausgeführt wird. var manager = null; function pageLoad() { manager = Sys.WebForms.PageRequestManager.getInstance(); manager.add_initializeRequest(pruefeStatus); }
Der Event-Handler prüft zuerst, ob der PageRequestManager existiert und ob es sich um einen asynchronen Aufruf handelt (get_isInAsyncPostBack()). Anschließend erhalten Sie aus dem zweiten Parameter des Event-Handler die Information, welches Element für den PostBack verantwortlich war. Ist es die Abbrechen-Schaltfläche, wird der PostBack mit abortPostBack() abgebrochen und mit args.set_cancel(true) jeder Neuversuch unterdrückt. function pruefeStatus(sender, args) { if (manager != null && manager.get_isInAsyncPostBack() && args.get_postBackElement().id == 'Abbrechen') { manager.abortPostBack(); args.set_cancel(true); } }
schnell + kompakt
31
2 – UpdatePanel und Co.
Abb. 2.7: Das Laden wird gestartet ...
Abb. 2.8: ... und wieder abgebrochen
In dieser Konstellation lädt die Abbrechen-Schaltfläche selbst dann einen PostBack, wenn sie angeklickt wird, während kein PostBack läuft. Dies können Sie verhindern, indem Sie immer mit set_cancel() die Übermittlung abbrechen:
32
ScriptManager und Co.
if (args.get_postBackElement().id == 'Abbrechen') { args.set_cancel(true); }
Hinweis Einen kompletten Überblick über die PageRequestManager-Klasse erhalten Sie in der Referenz unter http://ajax.asp.net/docs/ ClientReference/Sys.WebForms/PageRequestManagerClass/ default.aspx.
2.5 ScriptManager und Co. Das ScriptManager-Control ist das Herzstück von Microsoft Ajax und wird in diesem Abschnitt deswegen etwas ausführlicher gewürdigt. Der ScriptManager wird nicht nur für UpdatePanel und Konsorten benötigt, sondern hier binden Sie auch Web Services und eigene JavaScript-Skripte ein. Besonders aufpassen müssen Sie bei verschachtelten Seiten, da immer nur ein ScriptManagerControl auf einer Seite liegen darf.
2.6 Skripte einbinden Sie können im ScriptManager Web Services und andere JavaScript-Skripte einbinden. In Kapitel 4 erfahren Sie, wie Web Services funktionieren. Hier ein kleines Beispiel für ein Skript:
schnell + kompakt
33
2 – UpdatePanel und Co.
Damit das Skript komplett geladen ist, wenn Microsoft Ajax die JavaScript-Funktion pageLoad() ausführt, sollten Sie am Ende des eingebundenen Skripts noch folgenden Code hinzufügen: if (typeof(Sys) != "undefined") { Sys.Application.notifyScriptLoaded(); }
Hinweis Für das ScriptReference-Control können Sie noch einige Attribute setzen. Sie haben unter anderem die Möglichkeit, ein JavaScript-Skript aus einer Assembly einzusetzen. Das kommt z.B. beim Microsoft Ajax Futures CTP zum Einsatz. Eine Übersicht über die Möglichkeiten erhalten Sie unter http://ajax.asp.net/docs/mref/T_System_Web_UI_ScriptRefer ence.aspx.
2.7 Verschachtelte Sites Pro Seite ist nur ein ScriptManager-Control erlaubt. Das gilt auch bei verschachtelten Elementen mit Masterseiten und User-Controls. Sollte eines der verschachtelten Elemente allerdings noch eigene Erweiterungen benötigen – z.B. ein eigenes JavaScriptSkript –, können Sie dort das ScriptManagerProxy-Control einsetzen:
34
Programmieransätze
Abb. 2.9: Zwei ScriptManager sind nicht möglich
2.8 Programmieransätze UpdatePanel, ScriptManager etc. lassen sich nicht nur deklarativ, sondern auch per serverseitiger Programmierung steuern. Das Herzstück ist auch hier der ScriptManager bzw. die ScriptManager-Klasse. Sie haben zum Beispiel die Möglichkeit, mit der Methode RegisterAsyncPostbackControl() ein Control für das Aktualisieren von UpdatePanel-Bereichen anzugeben. Außerdem sind natürlich, wie in ASP.NET gewohnt, Attribute, die deklarativ gesetzt werden können, auch per Programmierung setzbar. UpdatePanels lassen sich über die Klasse UpdatePanel steuern. Hier gibt es beispielsweise die Methode Update(), die serverseitig eine Aktualisierung hervorruft.
schnell + kompakt
35
2 – UpdatePanel und Co.
Das folgende Beispiel verbindet die Steuerung von ScriptManager und UpdatePanel. Das UpdatePanel wird auf Knopfdruck aktualisiert, allerdings erfolgt die Verbindung nicht deklarativ per Trigger, sondern per Programmierung. Dafür muss der UpdateMode des UpdatePanel in Conditional geändert werden:
Die Aktualisierung erfolgt in der Schaltfläche bei Klick. Die serverseitige Methode ruft die Update()-Methode des UpdatePanel auf: protected void Button1_Click(object sender, EventArgs e) { UpdatePanel1.Update(); }
Damit nun kein kompletter PostBack durchgeführt wird, muss die Schaltfläche noch für asynchrone Aufrufe registriert werden. Das geschieht beim Laden der Seite mit der RegisterAsyncPostBackControl()-Methode des ScriptManager:
36
Fehlerhandling
protected void Page_Load(object sender, EventArgs e) { ScriptManager1.RegisterAsyncPostBackControl(Button1); Random ran = new System.Random(); Int32 zahl = ran.Next(0, 100000); Label1.Text = zahl.ToString(); Label2.Text = zahl.ToString(); }
Hinweis Eine komplette Übersicht erhalten Sie in der Server-Referenz der ASP.NET Ajax-Dokumentation (http://ajax.asp.net/docs/ mref/R_Project.aspx).
2.9 Fehlerhandling Der ScriptManager kann auch für das Fehlerhandling verwendet werden. Dazu gibt es die Eigenschaft OnAsyncPostBackError:
Diese serverseitige Methode verarbeitet Fehlermeldungen, die auf dem Server auftreten. Im einfachsten Fall übergeben Sie die Nachricht mit dem Fehler an den ScriptManager, um sie clientseitig auszugeben: protected void PostbackError(object sender, AsyncPostBackErrorEventArgs e) { ScriptManager1.AsyncPostBackErrorMessage = e.Exception.Message; }
schnell + kompakt
37
2 – UpdatePanel und Co.
Nun müssen Sie nur noch auf Knopfdruck einen Fehler beim asynchronen Aufruf produzieren. Dazu benötigen Sie eine Schaltfläche, die einen asynchronen Aufruf einer serverseitigen Methode (hier Fehler()) provoziert:
Für den asynchronen Aufruf muss sich die Schaltfläche entweder im UpdatePanel befinden oder per Trigger bzw. per serverseitiger Programmierung als asynchrones Control registriert sein. Der provozierte Fehler kann hier natürlich künstlich sein. Geben Sie dazu einfach eine Exception an: protected void Fehler(object sender, EventArgs e) { throw new Exception("Klappt nicht!"); }
38
KAPITEL 3 JavaScript-API 3.1
pageLoad()
40
3.2
$get()
40
3.3
Event-Handler
41
3.4
Elemente
44
3.5
Erweiterte JavaScript-Objekte
47
3.6
StringBuilder
50
Microsoft ASP.NET Ajax besteht nicht nur aus serverseitigen Komponenten und Web-Service-Integration, sondern auch aus einer umfangreichen JavaScript-API. Sie steht als separater Download zur Verfügung, ist aber auch in die normalen Ajax Extensions integriert. Sobald Sie einen ScriptManager auf der Seite integriert haben, werden die entsprechenden JavaScriptBibliotheken eingebunden und die API steht zur Verfügung. Hinweis In Atlas, der Vorabversion von Microsoft ASP.NET Ajax, gehörte XML-Script, eine deklarative clientseitige Sprache, zum Standardumfang. In der finalen Version wurde sie in den Futures CTP verbannt und die komplette Steuerung erfolgt per JavaScript. Die Dokumentation – egal ob online oder offline – enthält eine Referenz mit allen clientseitigen Funktionalitäten der JavaScriptAPI. In diesem Kapitel stellen wir Ihnen wichtige Bestandteile der API vor. Einige Funktionen lernen Sie auch in den folgenden Kapiteln kennen oder haben Sie wie den PageRequestManager schon kennengelernt. Alle in diesem Buch vorgestellten und
schnell + kompakt
39
3 – JavaScript-API
ebenso die nicht vorgestellten Teile finden Sie unter http:// ajax.asp.net/docs/ClientReference/. Organisiert ist die JavaScript-API in Namensräume, ähnlich wie das .NET Framework. Erweiterungen für JavaScript-Objekte und Kurzformen für den Zugriff auf Elemente finden Sie im Namensraum Global. Dort ist zum Beispiel der Zugriff auf Elemente per $get() enthalten. Die übrigen Namensräume enthalten zum einen die Funktionalität, auf der die Kurzformen wie $get() basieren, zum anderen auch verschiedenste Microsoft-Erweiterungen.
3.1 pageLoad() Zur clientseitigen API gehört auch die Funktion pageLoad(), die Sie im letzten Kapitel schon kennengelernt haben. Sie wird ausgeführt, wenn das Dokument und alle Skripte geladen sind. Gerade das Laden externer Skripte wird nämlich vom JavaScriptEreignis window.onload nicht abgefangen. Damit bei einem externen Skript auch wirklich geladen wird, müssen Sie es immer mit einem Zusatz versehen: if (typeof(Sys) != "undefined") { Sys.Application.notifyScriptLoaded(); }
3.2 $get() Wenn Sie auf Elemente zugreifen, setzen Sie in modernen JavaScript-Anwendungen auf document.getElementById(). Microsoft ASP.NET Ajax bietet dafür eine Hilfsfunktion namens $get(ID). Die folgende Zeile greift auf das Element mit der ID ausgabe zu und füllt es mit einem Text: $get("ausgabe").innerHTML = "Neuer Text";
40
Event-Handler
Alternativ können Sie natürlich auch CSS-Eigenschaften so einsetzen, wie Sie das in JavaScript schon lange gewohnt sind: $get("ausgabe").style.color = "red";
Wenn Sie Elemente nur unterhalb bestimmter anderer Elemente finden möchten, gibt es für $get(Element, Elternelement) einen zweiten Parameter, die ID des Elternelements. In diesem Fall wird das Element nur gefunden, wenn es sich unterhalb des Elternelements befindet. Hinweis $get() besitzt in der JavaScript-API auch eine Langform: Sys.UI.DomElement.getElementById(ID). Geliefert wird also ein
DOM-Element. In der Praxis verwendet man allerdings die kurze Variante.
3.3 Event-Handler Event-Handler sind Funktionen, die in JavaScript auf Ereignisse reagieren. Im einfachsten Fall können Sie über die entsprechenden HTML-Attribute onclick, onmouseover etc. aufgerufen werden. Im etwas komplexeren Fall werden sie Ereignissen zugewiesen, z.B. so: window.onload = function() { //Anweisungen };
Diese Möglichkeiten kapselt $addHandler(Element, Ereignis, Funktion) in einer einfachen Hilfsfunktion. Damit wird auch die ursprüngliche Intention erreicht, den Zugriff auf Ereignisse Browser-übergreifend zu gewährleisten. Denn leider haben In-
schnell + kompakt
41
3 – JavaScript-API
ternet Explorer und der Rest der Welt lange Zeit unterschiedliche Ansätze verfolgt. Sie geben in $addHandler() das Element an, auf das das Ereignis angewendet wird. Wichtig ist, dass es sich um das Element selbst handelt, nicht nur die ID. Anschließend folgt das betroffene Ereignis. Die Namen entsprechen den JavaScriptEreignissen, nur ohne vorangestelltes „on“. Der dritte Parameter ist die Funktion, die aufgerufen wird. Ereignisse können Sie natürlich verschiedenen Elementen zuweisen. Für ein erstes Beispiel soll eine Schaltfläche zum Einsatz kommen:
Der Event-Handler wird in pageLoad() hinzugefügt: function pageLoad() { $addHandler($get("event"), "click", handler); }
Die Handler-Funktion selbst gibt im -Block einen Text aus (Abbildung 3.1): function handler() { $get("ausgabe").innerHTML = "Schaltfläche geklickt"; } $addHandler() ist eine Kurzform von Sys.UI.DomEvent. Sie können dementsprechend im Event-Handler auch die Eigenschaften für ein DomEvent verwenden. Eine Eigenschaft davon sind die angeklickten Koordinaten auf dem Bildschirm screenX und screenY (Abbildung 3.2):
42
Event-Handler
function handler(e) { $get("ausgabe").innerHTML = "Klickkoordinaten: " + e.screenX + " und " + e.screenY; }
Abb. 3.1: Die einfachste Form eines Ereignisses
Abb. 3.2: Die Koordinaten werden ausgelesen
schnell + kompakt
43
3 – JavaScript-API
Hinweis Einen vollständigen Überblick über die Eigenschaften des Ereignisses liefert http://ajax.asp.net/docs/ClientReference/ Sys.UI/DomEventClass/default.aspx. Bei den Kurzformen finden sich neben $addHandler() noch weitere Möglichkeiten für Event-Handler. $addHandlers(Element, Ereignis-Handler-Paare) fügt einem Element mehrere Ereignisse hinzu. Die Ereignisse werden als Objekt angelegt. Das Ereignis ist der Name und die Handler-Funktion ist der Wert. Event-Handler lassen sich allerdings nicht nur hinzufügen. Mit $removeHandler(Element, Ereignis, Handler) löschen Sie einen Event-Handler. $clearHandlers(Element) entfernt alle EventHandler eines Elements.
3.4 Elemente Die JavaScript-API von Microsoft ASP.NET Ajax unterscheidet mehrere Arten von Elementen, die hauptsächlich im Namensraum Sys.UI zu finden sind. Die einfachste Form ist ein DomElement, sprich ein beliebiges HTML-Element, auf das Sie per DOM-Baum zugreifen. Dies entspricht beispielsweise dem Schnellzugriff mit $get(). Das DOM-Element erlaubt allerdings auch Zugriff auf Position und Maße eines Elements und dient dazu, CSS-Klassen hinzuzufügen und zu entfernen. Komponenten basieren dagegen auf der Basisklasse Sys.Component. Sie erweitern bestehende Objekte, sind selbst aber keine Elemente für die UI, sprich die Nutzeroberfläche. UI-Objekte, die auf Sys.Component basieren, sind Controls und Behavior.
44
Elemente
DomElement Das DomElement bietet verschiedene spannende Methoden, die Sie sehr leicht einsetzen können. Sie schreiben einfach den kompletten Namensraum, gefolgt von der Klasse und der Methode – das entspricht einem statischen Aufruf. Das betroffene Element ist immer der erste Parameter. Hier einige interessante Methoden im Überblick: 쐌 getBounds(Element) liefert ein Objekt mit vier Eigenschaften, x und y für die Koordinaten, außerdem width und height. Setzen lassen sich die Werte nur über die CSS-Befehle oder die Koordinaten über setLocation(). 쐌 getLocation(Element) liefert x- und y-Koordinaten eines Elements. 쐌 setLocation(Element, x, y) setzt ein Element an die angegebenen Koordinaten. Die Positionierung erfolgt dabei automatisch absolut (CSS-Wert für position ist absolute). Sys.UI.DomElement.setLocation($get("ausgabe"), 100, 200);
쐌 addCssClass(Element, Klasse) fügt eine CSS-Klasse hinzu. Ein Beispiel finden Sie in Kapitel 4. Hinweis Intern setzt ASP.NET die class-Eigenschaft aus JavaScript. Das heißt auch, dass Sie mehrere Klassennamen durch Leerzeichen separiert hintereinanderpacken können. Da diese Funktionalität aber nicht dokumentiert ist, ist eher davon abzuraten. 쐌 removeCssClass(Element, Klasse) entfernt eine CSS-Klasse. Auch dazu ist ein Beispiel in Kapitel 5 zu finden.
schnell + kompakt
45
3 – JavaScript-API
쐌 containsCssClass(Element, Klasse) prüft, ob eine Klasse für das Element vorhanden ist. 쐌 toggleCssClass(Element, Klasse) schaltet eine Klasse je nach aktuellem Status ein oder aus.
Komponenten, Controls und Behavior Komponenten bilden die Basis von Controls und Behavior. In den meisten Fällen werden Sie eigene Klassen schreiben, die bestehende Controls erweitern. Auf Controls können Sie aber auch direkt zugreifen. Ein Control lässt sich als neues Objekt anlegen: var control = new Sys.UI.Control(Element);
Damit es dann in der gesamten Applikation zur Verfügung steht, müssen Sie es mit der Methode addComponent(Control) zur Application hinzufügen: Sys.Application.addComponent(control);
Und schließlich gibt es noch eine Kurzform für den Zugriff auf registrierte Komponenten: $find() arbeitet ähnlich wie $get(). Der erste Parameter ist die ID des Elements, der zweite optionale Parameter die ID des Elternelements. Allerdings werden hier Komponenten gefunden und nicht DOM-Elemente. Das folgende Beispiel besteht aus einem Control und einer Schaltfläche: Control-Inhalt
46
Erweiterte JavaScript-Objekte
Das Control ist standardmäßig ausgeblendet. In pageLoad() blenden Sie es wieder ein, denn bei Controls können Sie die Sichtbarkeit steuern (siehe auch ein Beispiel in Kapitel 4). Außerdem erhält die Schaltfläche einen Event-Handler und das Control wird als Komponente registriert: function pageLoad() { var control = new Sys.UI.Control($get("control")); Sys.Application.addComponent(control); control.set_visible(true); $addHandler($get("controlButton"), "click", controlAusblenden); }
Zum Ausblenden wird schließlich die Methode set_visible() verwendet. Der Zugriff auf das Control erfolgt per $find(): function controlAusblenden() { $find("control").set_visible(false); }
Hinweis Eigene Komponenten, Controls und Behavior schreiben Sie, indem Sie Sys.Component bzw. Sys.UI.Control und Sys.UI.Behavior erweitern. Beispiele finden Sie unter http://ajax.asp. net/docs/tutorials/ASPNETAJAXExtensibilityTutorials.aspx.
3.5 Erweiterte JavaScript-Objekte Wer viel mit JavaScript entwickelt, kennt natürlich die Grenzen von JavaScript und weiß, dass ein umfangreiches Paket an Hilfsfunktionen notwendig sein kann. Microsoft ASP.NET Ajax besitzt bereits direkt integrierte Hilfen. Zu finden sind diese Funk-
schnell + kompakt
47
3 – JavaScript-API
tionen als JavaScript Base Type Extensions in der Referenz (http:/ /ajax.asp.net/docs/ClientReference/Global/JavascriptTypeExtensions/). Profitipp Sehr praktisch sind auch die Cheat Sheets von Milan Negovan. Hier erhält man einen tollen Überblick (http://aspnetresources.com/blog/ms_ajax_cheat_sheets_batch1.aspx). Mit den hier vorgestellten Methoden können Sie beispielsweise zu einem Array einfach Elemente hinzufügen und bestehende Elemente entfernen. Die Methode forEach() ruft für jedes Element eine JavaScript-Funktion auf: var a = new Array(1, 2, 3); Array.forEach(a, Methode, Kontext);
Als dritter Parameter wird hier ein vom Nutzer wählbarer Kontext bzw. eine Zusatzinformation übermittelt, die dann per this in der Event-Handler-Methode ankommt. Hier ein einfaches Beispiel, das die Inhalte eines Arrays multipliziert: var ergebnis = 0; function pageLoad() { var a = new Array(1, 2, 3); Array.forEach(a, rechnen, "+"); $get("ausgabe").innerHTML = ergebnis; } function rechnen(wert, index, array) { if (this == "+") { ergebnis += wert; } }
48
Erweiterte JavaScript-Objekte
In der Praxis müssten Sie natürlich noch prüfen, ob auch alle Inhalte des Arrays eine Zahl sind oder ob sich z.B. Strings darunter gemischt haben.
Abb. 3.3: Richtig gezählt: Dank Array-Erweiterung lässt sich ein Array mittels Funktionsaufrufen durchgehen
Das Datum lässt sich mit lokalem Format ausgeben und auch für Zahlen gibt es Formatierungsangaben. Die Formatierungen richten sich dabei nach den aus dem .NET Framework bekannten Standards. Sie sollen es .NET-Entwicklern also erleichtern, mit JavaScript zurechtzukommen. Hier ein Beispiel für das Datum im lokalen Format: var datum = new Date(); $get("ausgabe").innerHTML = datum.localeFormat("dd. MMMM yyyy HH:mm:ss");
Das lokale Format wird nur dann korrekt in Deutsch angezeigt, wenn die CulturInfo Deutsch ist. Sie können sie in der Page-Direktive setzen:
schnell + kompakt
49
3 – JavaScript-API
Alternativ ist auch das Setzen per Skript möglich. Damit die Angaben lokal übernommen werden, muss im ScriptManager die Eigenschaft EnableScriptGlobalization auf true gesetzt sein:
Abb. 3.4: Ein deutscher Monatsname
Für Strings besonders praktisch sind die trim-Methoden. Damit entfernen Sie Leerzeichen und anderen Whitespace am Anfang und/oder am Ende eines Strings: var text = " Ein String text = text.trim();
";
liefert also „Ein String“.
3.6 StringBuilder Der StringBuilder aus dem Sys-Namensraum ist eine weitere Microsoft-Hilfsfunktion für JavaScript. Er dient dazu, Strings zu konkatenieren, sprich, miteinander zu verbinden. Sie instanziie-
50
StringBuilder
ren ihn als Objekt und können dabei schon einen ersten String hinzufügen. Weitere Strings kommen dann mit append() hinzu. appendLine() fügt ebenfalls Strings an, allerdings mit Zeilenumbruch (\n und nicht HTML-Zeilenumbruch). Mit der Methode toString(Trennzeichen) lässt sich der String wieder in einen Gesamtstring aufteilen. Dabei haben Sie auch die Möglichkeit, ein Trennzeichen anzugeben. Das folgende Beispiel nimmt Einzelstrings und fügt diese mit Leerzeichen getrennt hintereinander: function pageLoad() { var text1 = "Hallo"; var text2 = "StringBuilder"; var sb = new Sys.StringBuilder("Los geht es:"); sb.append(text1); sb.append(text2); $get("ausgabe").innerHTML = sb.toString(" "); }
Abb. 3.5: Der String wird zusammengebaut
schnell + kompakt
51
KAPITEL 4 Web Services und Co. 4.1
Web Services
53
4.2
Forms Authentication Services
66
4.3
Profile Services
75
Der Datenaustausch zwischen Client und Server erfolgt in Microsoft ASP.NET Ajax standardmäßig per UpdatePanel und teilweiser Aktualisierung einer Seite. In diesem Fall sind Client und Server allerdings in einer ASPX-Seite verbunden, was Wiederverwertbarkeit und Flexibilität einschränkt. Deswegen gibt es die Möglichkeit, per ASP.NET Ajax auch Web Services aufzurufen und abzufragen. ASP.NET Ajax bietet außerdem noch zwei andere Arten von Diensten: die zur Formularauthentifizierung und die Profile-Services. Sie erlauben die clientseitige Nutzung der Authentifizierungs- und Personalisierungsmöglichkeiten aus ASP.NET 2.0 und werden auch Application Services genannt.
4.1 Web Services Der Begriff Web Services (oder dt. Webdienst) bezeichnet eine Sammlung von Standards, die den Nachrichtenaustausch zwischen Anwendungen über meist in XML gehaltene Formate erlauben. Die Kerntechnologien für den Nachrichtenaustausch
schnell + kompakt
53
4 – Web Services und Co.
sind SOAP und WSDL. Beide Standards werden vom W3C – dem Gralshüter des Web – verwaltet. Sie sind mittlerweile in mehrere Dokumente unterteilt. SOAP (http://www.w3.org/TR/ soap12-part0/) liefert das Aussehen der Nachrichten, WSDL (http: //www.w3.org/2002/ws/desc/) beschreibt das Außenherum so, dass Web-Service-Implementierungen in verschiedenen Technologien die Nachrichten verstehen können. Der Sinn von Web-Service-Nachrichten ist, Daten von einer Anwendung mit einer anderen auszutauschen. Dazu wird von der einen Anwendung eine Anfrage geschickt, die eine Methode aufruft. Die andere Anwendung führt die Methode aus und liefert das Ergebnis zurück. Dieser Prozess wird nun von Microsoft ASP.NET Ajax verwendet, um zwischen dem Client und dem Server zu kommunizieren. Auf dem Client erfolgt der Aufruf, der Server führt die Methode aus und liefert das Ergebnis zurück. Die nächsten Abschnitte beschreiben, wie Sie diese Kommunikation einrichten.
Web Service einrichten Als Erstes benötigen Sie einen neuen Web Service. Fügen Sie dazu in Visual Web Developer oder Visual Studio ein neues Element zu Ihrer Website hinzu (entweder über das Kontextmenü im PROJEKTMAPPEN-EXPLORER oder über DATEI/NEUE DATEI). Wählen Sie im Dialog einen WEBDIENST. Wir nennen ihn hier RECHNEN. Sie können den Code in eine eigene Datei packen. Diese landet dann automatisch im Verzeichnis APP_CODE.
54
Web Services
Abb. 4.1: Einen Webdienst anlegen
Sie sehen im angelegten Web Service schon eine Methode HelloWorld(). Wir wollen diese aber durch eine eigene Methode ersetzen, die zwei Parameter übernimmt und den zweiten vom ersten abzieht. [WebMethod] public Int32 Subtrahieren(Int32 a, Int32 b) { return a - b; }
Damit der Web Service und diese Methode clientseitig eingesetzt werden können, müssen Sie noch mit using System.Web.Script.Services;
schnell + kompakt
55
4 – Web Services und Co.
die entsprechende Klasse aus Microsoft ASP.NET Ajax importieren und den Web Service selbst mit dem Zusatz [ScriptService] versehen. Hier der vollständige Code, den Sie auch einsetzen können, wenn Sie keinen Editor verwenden: using using using using using using
System; System.Web; System.Collections; System.Web.Services; System.Web.Services.Protocols; System.Web.Script.Services;
[WebService(Namespace = "http://www.hauser-wenz.de/ Rechnen/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [ScriptService] public class Rechnen : System.Web.Services.WebService { [WebMethod] public Int32 Subtrahieren(Int32 a, Int32 b) { return a - b; } }
An sich liefert ein Web Service nur XML zurück. Zum Testen bietet ASP.NET allerdings die Möglichkeit, den Web Service direkt im Browser aufzurufen. Sie erhalten dann die vorhandenen Methoden. Klicken Sie die Methode an, haben Sie sogar die Möglichkeit, sie zu testen. Dies funktioniert leider nur bei einfachen Datentypen, nicht bei Arrays und Objekten. Außerdem sehen Sie die jeweiligen SOAP-Nachrichten, die der Dienst bereitstellt.
56
Web Services
Abb. 4.2: Der Web Service lässt sich zum Testen direkt aufrufen
Web Service aufrufen Um einen Web Service clientseitig aufzurufen, sind mehrere Schritte notwendig. Zuerst müssen Sie ihn im ScriptManager registrieren. Dazu dient die Sektion :
Dort legen Sie den Web Service als ServiceReference an und verweisen im Attribut Path auf die ASMX-Datei. Das einzige weitere
schnell + kompakt
57
4 – Web Services und Co.
Attribut ist InlineScript. Damit legen Sie fest, dass der Code für die Kapselung des Web Service direkt im Dokument angelegt wird, statt als externe JavaScript-Datei gelinkt zu sein. Das bietet sich vor allem für Testzwecke an, ist aber standardmäßig deaktiviert. Um an die Web-Service-Methode nun Daten zu übermitteln, benötigen Sie zuerst einmal die Nutzerschnittstelle, sprich das Formular. a b
Außerdem gibt es ein -Element für das Ergebnis mit der ID ergebnis: Ergebnis
Den Web-Service-Aufruf können Sie nun auf verschiedene Arten starten. Als Ereignis kommt hier natürlich nur das Anklicken der Schaltfläche in Frage. Sie können nun mit onclick direkt in HTML das Ereignis hinzufügen oder Sie verwenden die clientseitige Event-Handler-Hilfsfunktion $addHandler() von Microsoft ASP.NET Ajax (siehe vorheriges Kapitel): function pageLoad() { $addHandler($get("Subtrahieren"), "click", function() { Rechnen.Subtrahieren($get("a").value, $get("b").value, subtrahierenSuccess, subtrahierenError, 'ergebnis');
58
Web Services
} ); }
Der Web-Service-Aufruf ist im Listing hervorgehoben. Sie sehen, dass der Web Service einfach mit der Klasse und anschließend der Methode aufgerufen wird. Damit das funktioniert, muss er vorher im ScriptManager registriert worden sein. Die ersten zwei Parameter sind die Parameter der Web-Service-Methode. Wie viele das sind, richtet sich natürlich nach der Methode. Der nächste Parameter ist der Event-Handler, der im Erfolgsfall aufgerufen wird, der folgende ist der Event-Handler für den Misserfolg. Anschließend folgt noch ein optionaler Parameter, der den Event-Handlern mitgegeben werden kann. Hier ist das der Name des Elements, in dem das Ergebnis ausgegeben werden soll. Der Event-Handler für den Erfolg übernimmt das Ergebnis des Web-Service-Aufrufs und den vorhin erwähnten optionalen Parameter. Anschließend wird das Ergebnis ausgegeben: function subtrahierenSuccess(ergebnis, ausgabe) { $get(ausgabe).innerHTML = ergebnis; }
Optional ließe sich als dritter Parameter noch der Name der aufrufenden Web-Service-Methode übergeben. In unserem Fall ist das aber nicht notwendig. Im Misserfolgsfall wird statt des Ergebnisses ein Fehler geliefert. Dessen Meldung lässt sich mit get_message() ausfiltern und ausgeben.
schnell + kompakt
59
4 – Web Services und Co.
function subtrahierenError(fehler, ausgabe, methode) { $get(ausgabe).innerHTML = fehler.get_message() + " gemeldet von " + methode; }
Auch hier ist der zweite Parameter das von uns übergebene Element. Der dritte Parameter ist auch hier die aufrufende Web-Service-Methode. Das ist sinnvoll, wenn Sie mehrere Web-ServiceAufrufe mit demselben Event-Handler abfangen wollen. Vor allem im Fehlerfall kann das natürlich sinnvoll sein.
Abb. 4.3: Der Web Service rechnet für uns
Hinweis Web Services dürfen nur innerhalb derselben Domain aufgerufen werden, sogenannte Cross Domain-Aufrufe sind also nicht möglich. Diese Beschränkung resultiert aus Sicherheitsfunktionen des XMLHttpRequest-Objekts im Browser. Als Abhilfe bietet sich ein serverseitiger Web Service-Proxy an, der ex-
60
Web Services
terne Web Services abfragt und die Daten dann – natürlich geprüft – an den Client weiterreicht.
Fehlerhandling Um das Fehlerhandling zu testen, können Sie im Web Service noch eine Überprüfung integrieren. Im Beispiel darf die zweite Zahl nicht größer als die erste sein: if (b > a) { throw new Exception("Erste Zahl muss größer als zweite Zahl sein!"); }
Ansonsten wird ein Fehler zurückgemeldet. Diesen verarbeitet dann subtrahierenError() und gibt die Meldung sowie den dafür verantwortlichen Methodennamen aus.
Abb. 4.4: Die Anwendung meldet einen Fehler
schnell + kompakt
61
4 – Web Services und Co.
Hinweis Weitere Tests sind in der Realität natürlich sehr zu empfehlen. Wenn Sie z.B. wie hier Zahlen als Parameter erhalten, sollten Sie auch prüfen, ob es sich wirklich um Zahlen handelt, bevor Sie rechnen. Daten, die in eine Datenbank geschrieben werden, sind auf die Gefahren von SQL-Injections, also vor allem Apostrophe, zu filtern und bei Strings sollten je nach Einsatzgebiet die HTML-Tags und -Sonderzeichen verschwinden, um Sicherheitslücken zu vermeiden.
Datenaustausch Wenn Sie sich die von Microsoft ASP.NET Ajax gesendeten HTTP-Requests ansehen, erkennen Sie schnell, dass zur Serialisierung der Daten JSON eingesetzt wird. JSON ist eine Objektnotation für JavaScript-Datentypen. Für die zwei einfachen Zahlen aus dem Beispiel wird ein JavaScript-Objekt verwendet, das die Zahlen jeweils mit dem Feldnamen als Eigenschaft übermittelt. Hinweis Als Versandmethode verwendet Microsoft ASP.NET Ajax automatisch POST. Sie müssen GET für die jeweilige Methode explizit aktivieren: [ScriptMethod(UseHttpGet=true)]. Siehe hierzu auch http://weblogs.asp.net/scottgu/archive/2007/04/ 04/json-hijacking-and-how-asp-net-ajax-1-0-mitigates-theseattacks.aspx. Der Austausch erfolgt immer in JSON. Sie können allerdings auch ein XML-Dokument als Rückgabe einsetzen. Dazu geben Sie es einfach in einer WebMethod aus:
62
Web Services
[WebMethod] public XmlDocument Methode() { //XML einlesen return xml; }
Abb. 4.5: LiveHTTPHeaders – eine Firefox-Erweiterung – zeigt, dass das Standardaustauschformat JSON ist
schnell + kompakt
63
4 – Web Services und Co.
Profitipp Wenn Sie umfangreichere Daten austauschen, müssen Sie JSON mehr Zeichen geben, um den Datenaustausch durchführen zu können. Dazu gehen Sie in die Web.config. Dort gibt es die Sektion . Hier finden Sie Einstellungen für die JSON-Serialisierung. Die relevante Eigenschaft von ist maxJsonLength. Sie wird auf einen Wert in Zeichen gesetzt. Dort haben Sie außerdem die Möglichkeit, einen eigenen Serialisierer für JSON anzugeben. Ein entsprechendes Beispiel finden Sie in der Standard-Web.config, die für ein Microsoft ASP.NET Ajax-Projekt angelegt wird. Neben XML sind auch andere komplexe Datentypen wie Generics und Objekte austauschbar. Sie können komplexe Datentypen an den Web Service übergeben oder sie zurückerhalten. Natürlich ist auch eine Kombination aus beidem möglich. Ein Beispiel soll das illustrieren. Die Web-Service-Methode übernimmt eine Liste mit Dezimalzahlen, bildet für jede Zahl den Betrag und liefert das ganze zurück. Hier die entsprechende Methode: [WebMethod] public List Betrag(List Elemente) { List ElementeBetrag = new List(); foreach (Decimal Element in Elemente) { ElementeBetrag.Add(Math.Abs(Element)); } return ElementeBetrag; }
64
Web Services
Sie müssen außerdem noch für den Web Service Generics importieren: using System.Collections; using System.Collections.Generic;
Clientseitig ist der Aufruf sehr einfach: Sie erstellen ein Array mit den Zahlen, die umgewandelt werden sollen, und übergeben ihn als Parameter. Dies erfolgt der Einfachheit halber beim Laden der Seite. Natürlich könnten Sie auch dem Nutzer die Möglichkeit geben, die Daten einzugeben. function pageLoad() { var werte = new Array(-1, 5, -5); Rechnen.Betrag(werte, subtrahierenSuccess, subtrahierenError, 'ergebnis'); }
Im Erfolgsfall müssen Sie das zurückgegebene Array durchlaufen und die einzelnen Zahlen untereinander ausgeben: function subtrahierenSuccess(ergebnis, ausgabe) { for (var ele in ergebnis) { $get(ausgabe).innerHTML += ergebnis[ele] + ""; } }
Hinweis Einen Überblick über den Austausch verschiedener Datentypen bietet auch http://ajax.asp.net/docs/tutorials/ConsumingWebServicesWithAJAXTutorial.aspx.
schnell + kompakt
65
4 – Web Services und Co.
Abb. 4.6: Die Daten aus dem Array werden ausgegeben
4.2 Forms Authentication Services In ASP.NET 2.0 gibt es einige Neuerungen, die dem Entwickler viel Arbeit abnehmen. Dazu zählen die Login-Controls, hinter denen der Membership-Provider für die Authentifizierung und Nutzerdatenverwaltung steckt. Diese Art der Authentifizierung wird in Microsoft ASP.NET Ajax auch clientseitig unterstützt. Konkret gibt es eine Methode zum Prüfen der Einloggdaten (login()) und eine Methode zum Abmelden (logout()).
Serverseitig Bevor es clientseitig losgeht, müssen Sie zuerst die Formularauthentifizierung konfigurieren. Verwenden Sie zum Testen am
66
Forms Authentication Services
besten eine neue Website. Als Grundvoraussetzung benötigen Sie einen SQL Server. Im Editor geht das über die Website/ ASP.NET-Konfiguration. Alternativ können Sie die Einstellungen, die das Konfigurationstool liefert, auch direkt in der Web.config vornehmen. In der webbasierten ASP.NET-Konfiguration wechseln Sie zur Sicherheit. Dort können Sie den Assistenten starten. Die wichtigste Entscheidung fällt in Schritt 2. Dort wählen Sie die Zugriffsmethode. Die Formularauthentifizierung ist hier als AUS DEM INTERNET benannt.
Abb. 4.7: Die Formularauthentifizierung einschalten
In den übrigen Schritten sollten Sie keine Rollen hinzufügen und keinen anderen Datenspeicher wählen. Nur einen neuen Benutzer sollten Sie anlegen. Anschließend verweigern Sie den Zugriff
schnell + kompakt
67
4 – Web Services und Co.
für alle anonymen Nutzer. Das Konfigurationstool schreibt die entsprechenden Einstellungen direkt in die Web.config.
Die Verbindung zur Datenbank finden Sie bei den . Zu guter Letzt müssen Sie noch den Authentication Service in der Web.config aktivieren. Dies geschieht in der Sektion unter :
Clientseitig Ist serverseitig alles eingerichtet, geht es daran, die Authentifizierung abzufangen. Erstellen Sie dazu eine Seite Login.aspx. Das ist der Standardname für die Datei, auf die alle anderen Dateien weitergeleitet werden, wenn eine Authentifizierung notwendig ist. Diesen Namen können Sie übrigens auch in der Web.config ändern:
68
Forms Authentication Services
Herzstück des Authentication-Service ist dann die clientseitige Klasse Sys.Services.AuthenticationService und dort die zwei Methoden login() und logout(). Beide erwarten eine Reihe von Parametern. Bei login() müssen Sie Folgendes angeben: 쐌 Der erste Parameter ist der Nutzername als String. 쐌 Der zweite Parameter ist das Passwort als String. 쐌 Der dritte Parameter gibt an, ob die Authentifizierung per Cookie über die gesamte Browser-Sitzung beibehalten wird (true) oder nicht (false, Standardwert) 쐌 Der vierte Parameter gibt an, wohin nach erfolgreicher Anmeldung weitergeleitet wird. Standardwert ist null, sprich keine Weiterleitung. 쐌 Der fünfte Parameter ist noch nicht belegt, sondern von Microsoft für die Zukunft reserviert. Der Wert ist im Moment also null. 쐌 Der sechste Parameter gibt eine Funktion an, die bei erfolgreicher Anmeldung aufgerufen wird. Standardwert ist auch hier null. 쐌 Der siebte Parameter nennt die Funktion, die im Fehlerfall aufgerufen wird. Auch hier ist der Standardwert wieder null. 쐌 Der achte Parameter gibt einen vom Nutzer wählbaren Wert an, der an die zwei Event-Handler für Erfolg und Misserfolg übergeben werden kann. Dies entspricht dem Verfahren wie bei einem Web Service.
schnell + kompakt
69
4 – Web Services und Co.
Ein Aufruf kann dementsprechend so aussehen: Sys.Services.AuthenticationService.login("username", "password", false, null, null, loginErfolg, fehler, "Nutzerangabe");
Für das Ausloggen mit logout() stehen naturgemäß ein paar Parameter weniger zur Verfügung: 쐌 Als erster Parameter die URL, an die beim erfolgreichen Ausloggen weitergeleitet wird. Ist keine bzw. null angegeben, wird die aktuelle Seite neu geladen, um alle Einstellungen zurückzusetzen. Dieses Neuladen lässt sich auch nicht verhindern. Im Fehlerfall, z.B. weil der Dienst sich nicht korrekt authentifizieren lässt, erfolgt kein Neuladen. 쐌 Der zweite Parameter bestimmt die Funktion, die beim erfolgreichen Abmelden aufgerufen wird. 쐌 Der dritte Parameter ist der Event-Handler für den erfolglosen Aufruf. 쐌 Der vierte Parameter enthält Daten, die der Nutzer an die zwei Event-Handler mitgeben kann. Hier ein typischer Aufruf: Sys.Services.AuthenticationService.logout(null, logoutErfolg, fehler, "Nutzerangabe");
Hinweis Sie können für den Erfolgs- und Misserfolgsfall auch StandardEvent-Handler definieren, statt sie bei login() und logout() anzugeben. Dafür zuständig sind die Methoden set_defaultLoginCompletedCallback(), set_defaultLogoutCompletedCallback() und set_defaultfailedCallback(). Einige weitere Eigenschaften wie zum Beispiel isLoggedIn zur Prüfung, ob ein Nutzer
70
Forms Authentication Services
angemeldet ist, finden Sie in der Referenz unter http:// ajax.asp.net/docs/ClientReference/Sys.Services/AuthenticationServiceClass/default.aspx. Das folgende Beispiel fasst Ein- und Ausloggen zusammen. Als HTML-Grundlage kommen drei -Blöcke zum Einsatz. Der erste enthält das Formular zum Anmelden, der zweite das zum Abmelden und der dritte gibt eine Statusmeldung aus bzw. zeigt „geheime“ Informationen an: Nutzername Passwort
Nun zum JavaScript: Beim Laden der Seite in der Funktion pageLoad() setzen Sie den Event-Handler für das Anmelden. Hier könnten Sie auch Standard-Event-Handler für Login und Logout setzen. Außerdem werden hier die -Blöcke zum An- und Abmelden in Controls umgewandelt und der Logout-Block ausgeblendet: var loginControl = null; var logoutControl = null; function pageLoad() { $addHandler($get("Anmelden"), "click", login); loginControl = new Sys.UI.Control($get("login"));
schnell + kompakt
71
4 – Web Services und Co.
loginControl.set_visibilityMode(Sys.UI.VisibilityMode. collapse); logoutControl = new Sys.UI.Control($get("logout")); logoutControl.set_visibilityMode(Sys.UI.VisibilityMode. collapse); logoutControl.set_visible(false); }
Hinweis Für das Ein- und Ausblenden könnten Sie alternativ natürlich die Standard-DOM-Funktionen, sprich style.visibility oder style.display verwenden. Der Aufruf zum Anmelden erfolgt in der Funktion login(). Dort greifen Sie auf die Werte für Nutzername und Passwort aus den entsprechenden Formularfeldern zu. Im Erfolgsfall übernimmt der Event-Handler loginErfolg() vom Server ein Ergebnis, das entweder true, sprich korrekte Authentifizierung, oder false, keine Authentifizierung, bedeutet. Ist die Authentifizierung korrekt erfolgt, werden alle Anweisungen für authentifizierte Nutzer ausgeführt: Im vorliegenden Beispiel erfolgt eine entsprechende Ausgabe von „geheimen“ Daten, außerdem wird der Event-Handler für das Abmelden aktiviert, die Schaltfläche zum Abmelden eingeblendet und die Login-Maske ausgeblendet. Sollte die Authentifizierung scheitern, geschieht das nicht, sondern es wird eine entsprechende Meldung ausgegeben.
72
Forms Authentication Services
function login() { Sys.Services.AuthenticationService.login($get("username"). value, $get("password").value, false, null, null, loginErfolg, fehler, "ausgabe"); } function loginErfolg(ergebnis, kontext, methode) { if (ergebnis) { $get(kontext).innerHTML = "Streng geheime Daten!"; $addHandler($get("Abmelden"), "click", logout); loginControl.set_visible(false); logoutControl.set_visible(true); } else { $get(kontext).innerHTML = "Kein Zugriff!"; } }
Im Fehlerfall wird für Login und Logout derselbe Event-Handler verwendet. Wichtig ist: Der Fehlerfall ist nicht das erfolglose Einloggen. Letzteres ist in der Rückgabe des Login-Event-Handlers enthalten. Der Fehlerfall tritt z.B. bei einem vom Server gemeldeten Fehler ein. function fehler(fehler, kontext, methode) { $get(kontext).innerHTML = "Ein Fehler ist in " + methode + " aufgetreten: " + fehler; }
Das Ausloggen ist noch einfacher als das Einloggen. Hier ändern wir im Event-Handler für den Erfolgsfall nur den gemeldeten Text und schalten die Login-Maske wieder auf sichtbar.
schnell + kompakt
73
4 – Web Services und Co.
function logout() { Sys.Services.AuthenticationService.logout(null, logoutErfolg, fehler, "ausgabe"); } function logoutErfolg(ergebnis, kontext) { $get(kontext).innerHTML = "Ausgeloggt."; loginControl.set_visible(true); logoutControl.set_visible(false); }
Allerdings erscheinen diese Änderungen nur sehr kurz, da beim Abmelden automatisch die gesamte Seite neu geladen wird.
Abb. 4.8: Der Nutzer meldet sich an …
74
Profile Services
Abb. 4.9: … und ist ohne Neuladen angemeldet
Hinweis Wirft man einen Blick auf den HTTP-Verkehr, der bei der Authentifizierung ausgetauscht wird, sieht man, dass Nutzername und Passwort per JSON an den Server übergeben werden. Zurückgeliefert wird ein Cookie mit der Authentifizierung. Es kommt ab jetzt bei jedem XMLHttpRequest-Aufruf mit und stellt sicher, dass nur eingeloggte Nutzer zugreifen können.
4.3 Profile Services Profile sind eine Personalisierungsfunktionalität für ASP.NET 2.0. Sie vergeben in der Web.config Profileigenschaften und diese werden dann für jeden Nutzer gespeichert. So lassen sich Formatierungsinformationen, Positionen von Elementen und Werte für Einstellungen speichern.
schnell + kompakt
75
4 – Web Services und Co.
Serverseitig Serverseitig müssen Sie die Profile zuerst aktivieren. Dazu fügen Sie die -Sektion in ein. Die Profile müssen mit dem Attribut enabled aktiviert werden. Anschließend folgen die Profileigenschaften. Hier sind beliebige Datentypen wählbar. Für komplexere Datentypen kommt oft die JSON-Serialisierung zum Einsatz, so auch in diesem Beispiel. Hier werden CSS-Klassen, die der Nutzer wählen kann, per Profil gespeichert.
Mit können Sie Profile auch in Gruppen zusammenfassen. Eine Gruppe hat einen eigenen Namen. Hier ein Beispiel:
Hinweis Mit der Klasse Sys.Services.ProfileGroup können Sie sogar selbst Gruppen anlegen. Mehr dazu unter http://ajax.asp.net/ docs/ClientReference/Sys.Services/ProfileGroupClass/default.aspx.
76
Profile Services
Mit dem Anlegen der Profile und Eigenschaften sind Sie in der Web.config allerdings noch nicht fertig. Sie benötigen noch den . Er wird genau wie der definiert. Einzige Besonderheit ist, dass Sie jede Profileigenschaft, die Sie clientseitig verwenden möchten, hier noch einmal als les- und/oder schreibbar angeben müssen. Ansonsten steht sie nicht zur Verfügung.
Profitipp Die Profile-Services funktionieren auch mit anonymen Profilen. Anonyme Profile müssen per aktiviert sein und jede Profileigenschaft muss das Attribut allowAnonymous="true" besitzen.
Clientseitig Als Ausgangsbasis für ein Beispiel zur clientseitigen Profilabfrage und Speicherung dient das Login-Beispiel aus dem letzten Abschnitt. Dort soll der Nutzer – wenn er eingeloggt ist – zwischen CSS-Klassen wählen können. Diese Einstellungen werden dann per Profil gespeichert und beim Neuladen jeweils wieder aufgerufen.
schnell + kompakt
77
4 – Web Services und Co.
In der HTML-Seite benötigen Sie zwei Checkboxen für zwei CSSKlassen und eine Schaltfläche, die die Änderung übernimmt und im Profil speichert: CSS-Klassen einstellen Rot Invert
Zentral ist ein global definiertes JavaScript-Array mit den entsprechenden CSS-Klassen: var klassen = ["rot", "invert"];
In der Funktion login() wird bei erfolgreichem Login das Profil geladen und die Ändern-Schaltfläche mit einem Event-Handler versehen. Dazu fügen Sie folgenden Code hinzu: Sys.Services.ProfileService.load(null, profilErfolg, profilFehler, null); $addHandler($get("Aendern"), "click", klasseAendern);
Wenn das Profil erfolgreich geladen wurde, passieren mehrere Dinge: Die Profileigenschaft Klassen wird ausgelesen und mit Sys.Serialization.JavaScriptSerializer.deserialize() aus einem JSON-Array in JavaScript umgewandelt. Im Hintergrund werkelt hier ein JavaScript-eval()-Befehl. Anschließend geht das
78
Profile Services
Skript das Array durch, aktiviert die jeweilige Checkbox, wenn die Klasse enthalten ist, und fügt die CSS-Klasse hinzu: function profilErfolg(elemente, kontext, methode) { var klassenAktiv = Sys.Serialization.JavaScriptSerializer.deserialize(Sys.Ser vices.ProfileService.properties.Klassen); for (var i = 0; i < klassenAktiv.length; i++) { $get(klassenAktiv[i]).checked = true; Sys.UI.DomElement.addCssClass($get("ausgabe"), klassenAktiv[i]); } }
Der Event-Handler für das Laden des Profils erhält als Parameter die Zahl der geladenen Eigenschaften, den im Aufruf zusätzlich angegebenen Kontext und die Methode. Soll das Profil geändert werden, wird die Funktion klasseAendern() aufgerufen, die der Ändern-Schaltfläche zugewiesen ist. Sie übernimmt die aktivierten Checkboxen in einen Array, ändert gleich die angezeigten CSS-Klassen und speichert das Array per Profil: function klasseAendern() { var klassenAktiv = new Array(); for (var i = 0; i < klassen.length; i++) { var boxKlasse = $get(klassen[i]); if (boxKlasse.checked) { klassenAktiv.push(klassen[i]); Sys.UI.DomElement.addCssClass($get("ausgabe"), klassen[i]); } else { Sys.UI.DomElement.removeCssClass($get("ausgabe"), klassen[i]); }
schnell + kompakt
79
4 – Web Services und Co.
} Sys.Services.ProfileService.properties.Klassen = Sys.Serialization.JavaScriptSerializer.serialize(klassenAk tiv); Sys.Services.ProfileService.save(null, profilGespeichert, profilFehler, null); }
Für Speichern und Fehlersteuerung gibt es nun noch zwei EventHandler, die einfach nur eine entsprechende Fehlermeldung ausgeben. function profilGespeichert(elemente, kontext, methode) { alert(elemente + " Element(e) gespeichert"); } function profilFehler(fehler, kontext, methode) { alert("Fehler " + fehler.get_message() + " in " + methode); }
Abb. 4.10: Die CSS-Klassen wurden geändert und als Profil gespeichert
80
KAPITEL 5 Control Toolkit 5.1
Eigenständige Controls
86
5.2
Extender
89
Das Microsoft ASP.NET Ajax Control Toolkit ist eine von Microsoft initiierte (und kontrollierte) Community-Entwicklung, die auf CodePlex stattfindet. Von dort lässt sich – natürlich über den Umweg offizielle Microsoft Ajax-Seite – das Toolkit herunterladen. Das Control Toolkit enthält serverseitige Steuerelemente, die wie die normalen Web Controls deklarativ programmiert werden können. Verfügbar ist es mit und ohne Quellcode. Es besteht, wie schon im ersten Kapitel erwähnt, aus einem ZIP-Archiv mit einem zentralen Visual Studio- bzw. Visual Web Developer-Projekt AjaxControlToolkit.sln. Zum Ausprobieren können Sie einfach das Projekt öffnen. Später ist es sinnvoll, die einzelnen Controls in die Toolbox von Visual Studio oder Visual Web Developer zu integrieren. Dazu kopieren Sie die zugrunde liegende DLL, die Sprachressourcen und die PDB-Datei aus dem Verzeichnis SampleWebSite/Bin/ des ZIP-Archivs in ein Verzeichnis, in dem sie permanent liegen kann. Eine Möglichkeit ist ein Unterverzeichnis des MICROSOFT ASP-NET-Ordners (standardmäßig unter C:\Programme\). Hierfür müssen Sie die entsprechenden Rechte besitzen bzw. bestäti-
schnell + kompakt
81
5 – Control Toolkit
gen. Diese Kopie ist dann die Ausgangsbasis für die Elemente in der Toolbox und wird in alle Projekte kopiert, die Elemente aus der Toolbox einsetzen. Um die Controls zur Toolbox hinzuzufügen, klicken Sie mit der rechten Maustaste auf die Toolbox. Wählen Sie dann REGISTER HINZUFÜGEN. Sie können das Register nun durch Anklicken umbenennen. Zum Füllen wählen Sie im Kontextmenü ELEMENTE HINZUFÜGEN. Im Register .NET FRAMEWORK-KOMPONENTEN klicken Sie auf DURCHSUCHEN und gehen in das Verzeichnis mit der DLL. Wählen Sie die DLL AjaxControlToolkit.dll aus und bestätigen Sie mit ÖFFNEN.
Abb. 5.1: Die DLL auswählen
Nun sind die Controls aus dem Toolkit ausgewählt. Sie können die Liste durchscrollen und auch einzelne abwählen. Alle anderen werden mit OK übernommen.
82
Control Toolkit
Abb. 5.2: Hier wählen Sie Controls
Alle Controls werden in der Toolbox eingefügt. Um eines der Controls einzusetzen, ziehen Sie es einfach in die Entwurfs- oder Quellansicht. Die Assembly wird eingebunden und im Bin-Verzeichnis der jeweiligen Website landen die DLL, die Sprachressourcen und die PDB-Datei. Hier der Registriercode, den der Editor automatisch hinzufügt:
Alternativ können Sie die Assembly auch in der Web.config registrieren. Hier sehen Sie ein Beispiel mit einem anderen Präfix, nämlich ajaxToolkit:
schnell + kompakt
83
5 – Control Toolkit
Genauso geht auch die Vorlage des VSI-Installers im ZIP-Paket vor. Hinweis Sollten Sie ohne Editor arbeiten, kopieren Sie einfach DLL, Sprachressourcen und PDB-Datei von Hand und registrieren Sie die Assembly mit obigem Code.
Abb. 5.3: Die Toolbox enthält die Controls
84
Control Toolkit
Alle Controls tragen standardmäßig das Präfix cc1. Es ist beim Registrieren der Assembly definiert und kann dort auch für die Seite geändert werden. Vorsicht, Seiten mit Controls müssen auch einen ScriptManager enthalten. Wenn Sie anfangen, mit den Controls zu arbeiten, sollten Sie auf jeden Fall die mitgelieferte Beispielwebsite SAMPLEWEBSITE ausführen. Dort finden Sie für jedes Control ein Beispiel und die entsprechende Dokumentation zum Einsatz. Dort sind auch alle Attribute angegeben. Allerdings gibt es hier teilweise auch die üblichen Schwächen – Dinge haben sich schon geändert, Eigenschaften funktionieren nicht etc. Ein wenig Pioniergeist gehört also dazu.
Abb. 5.4: Die Dokumentation für ein Control
schnell + kompakt
85
5 – Control Toolkit
In den folgenden Abschnitten sollen nicht alle Controls vorgestellt werden: Zum einen ändern sie sich ständig, zum anderen erledigt das die Dokumentation sehr gut. Die Abschnitte zeigen vielmehr die unterschiedlichen Arten von Controls und jeweils einfache Beispiele, um die ersten Schritte zurückzulegen. Profitipp Wer bestehende Controls ändern oder eigene Controls anlegen möchte, wird im Control Toolkit mit Quellcode fündig. Dort finden sich VSI-Dateien für eigene Extender und im Ordner AjaxControlToolkit die Quellcodes aller Controls. Für einige Funktionen ist allerdings Visual Studio notwendig, so auch für eigene Extender-Projekte. Sie finden dann in Visual Studio ein ASP.NET Ajax Control Project und können dort ein aus C#bzw. VB.NET-Quellcode und JavaScript-Bibliothek bestehendes Control anlegen. Eine einfache Einführung hierzu erhalten Sie auch in der SampleWebSite unter CREATING A NEW EXTENDER.
5.1 Eigenständige Controls Die meisten Controls im Microsoft ASP.NET Ajax Control Toolkit sind sogenannte Extender – Erweiterungen bestehender Elemente. Es gibt allerdings auch eigenständige Controls. Das vermutlich bekannteste ist das Accordion. Es zeigt verschiedene Register, sogenannte Panes, zwischen denen der Nutzer dann per JavaScript – sprich ohne Neuladen – wechseln kann. Der grundlegende deklarative Code ist einfach. Sie ziehen das Accordion-Control in die Seite. Darin fügen Sie ein Tag ein. Außerdem könnten Sie hier noch Templates wählen. In den -Bereich fügen Sie nun AccordionPane-Controls ein. Diese wiederum erhalten - und -Elemente
86
Eigenständige Controls
Register 1 Inhalt von Register 1 Register 2 Inhalt von Register 2
Zum Formatieren ist nun noch ein wenig CSS-Code notwendig. Alternativ können Sie Formate auch per Attribut setzen. Hier sind die zentralen CSS-Klassen aber praktischer: body { font-family: Arial, Helvetica, sans-serif; } .accInhalt { background-color: blue; color: white; padding: 5px; } .accKopf { background-color: #cccccc; text-transform: uppercase; padding: 5px; }
schnell + kompakt
87
5 – Control Toolkit
Abb. 5.5: Das Accordion erlaubt den Wechsel vom einen ...
Abb. 5.6: … zum anderen Register
88
Extender
Hinweis Eine aktuelle Dokumentation mit allen Einstellungen beispielsweise für das Accordion finden Sie auch unter http:// ajax.asp.net/ajaxtoolkit/, wenn Sie die SampleWebSite gerade nicht zur Hand haben.
5.2 Extender Bei Extender-Controls ist wie schon erwähnt ein bestehendes Element die Basis. Dieses Element wird dann entsprechend „erweitert“, sprich mit zusätzlichen Funktionen versehen. Allerdings gibt es viele Funktionen, bei denen das ursprüngliche Element dann kaum mehr zu erkennen ist. Die folgenden Abschnitte zeigen ein paar Beispiele.
Formulare und Informationen Das erste Beispiel zeigt, dass manchmal auch zwei Elemente an der Erweiterung beteiligt sind. Der DropDownExtender macht ein Element wie beispielsweise ein Label zu einem DropDown. Die angezeigten Optionen wiederum können selbst ein Control sein. Hier wird z.B. eine ListBox eingesetzt:
schnell + kompakt
89
5 – Control Toolkit
Abb. 5.7: Ein Text als Auswahlliste
Eine dem Accordion ähnliche Methode, um Informationen kurzzeitig zu verstecken, ist CollapsiblePanel. Sie ist allerdings im Gegensatz zum Accordion nicht eigenständig, sondern erweitert ein anderes Element. Das kann zum Beispiel ein Panel sein:
Abb. 5.8: Ein Panel ein- ...
Abb. 5.9: … und ausgeklappt
schnell + kompakt
91
5 – Control Toolkit
Ein Extender, der sehr gut die mögliche Flexibilität zeigt, ist NumericUpDownExtender. In der einfachsten Version erweitert man ein Textfeld damit um zwei Schaltflächen, die numerische Werte im Textfeld hoch- und runterschalten. Sie können dabei mit dem Attribut Step die Schrittlänge einstellen.
Abb. 5.10: Schrittweise Änderung
Neben diesen einfachen Möglichkeiten gibt es allerdings noch komplexere Optionen. Sie können mit dem Attribut RefValues auch Strings als Werte angeben. Und mit ServiceDownPath bzw. ServiceUpPath geben Sie einen Pfad zu einem Web Service an. Mit ServiceDownMethod bzw. ServiceUpMethod bestimmen Sie die zugehörige Methode, die den jeweils nächst niedrigeren oder höheren Schritt liefert. Die Methode muss dementsprechend für clientseitiges Skripting freigegeben sein (siehe Kapitel 4). Wollen Sie eine Methode aus der aktuellen Datei verwenden, setzen Sie den Pfad einfach auf null.
92
Extender
Hinweis Das Control Toolkit hält noch weitere komplexere Controls bereit. CascadingDropDown bietet zum Beispiel eine Liste, die ihre Werte per Web Service holt. Ein Tutorial zum Auslesen von Datenbankdaten finden Sie hier: http://ajax.asp.net/ajaxtoolkit/ Walkthrough/CCDWithDB.aspx.
Modale Fenster Modale Fenster sind in JavaScript eigentlich per alert() aufgerufene Warnmeldungen oder per prompt() bzw. confirm() angezeigte Fenster mit Eingabe- oder Entscheidungsmöglichkeit. Im Web 2.0 kommen im Zuge des JavaScript-Booms andere Fenster zum Einsatz, die eigentlich keine richtigen Fenster sind. Das ModalPopup legt ein Element vor den Rest der Seite und erlaubt es, diesen abzudunkeln. Dazu benötigen Sie eine CSS-Klasse mit der Hintergrundfarbe: .hintergrund { background-color: black; }
Profitipp Für einen Transparenzeffekt verwenden Sie opacity und für den Internet Explorer den Filter alpha. Als Popup-Anzeige wird hier ein Panel verwendet. Der Aufruf erfolgt über eine Schaltfläche. Im Panel selbst gibt es wiederum eine Schaltfläche, die das Popup wieder schließt: Modales Fenster
schnell + kompakt
93
5 – Control Toolkit
Abb. 5.11: Ein Fenster mitten über der Anwendung
Hinweis Neben dem ModalPopup gibt es noch andere Controls wie das PopupControl, die Fenster oder Hinweise öffnen.
94
Extender
Effekte Animationen und Effekte finden sich in sehr vielen Ajax Controls aus dem Toolkit. Alle Effekte basieren dabei auf JavaScript und viele verwenden auch CSS-Klassen für die Funktionalität. Ein gutes Beispiel ist das ResizableControl. Hier ist eine CSS-Klasse Pflicht, die den Anfasser zum Skalieren definiert: .handleText { background-image: url(bilder/bewegen.png); width:19px; height:19px; overflow:hidden; cursor:se-resize; }
Wichtig ist das Hintergrundbild, denn dies ist das Bild für den Anfasser. Außerdem müssen Sie Breite und Höhe angeben, um den Anfasser überhaupt sehen zu können. Die Änderung des Mauszeigers ist dann nur Zugabe. Der ResizableControlExtender wird einfach auf ein Panel angewendet. Sie können Maximal- und Minimalgrößen vergeben und den Handler noch ein wenig verschieben: Veränderbares Fenster
schnell + kompakt
95
5 – Control Toolkit
Abb. 5.12: Vergrößern und verkleinern
Als zweiter Effekt soll hier noch die Animation zu Wort kommen. Dafür zuständig ist der AnimationExtender. Dieser Extender nimmt sich ein Zielcontrol mit TargetControlID und führt dann dafür Animationen aus. Die Animationen werden im Tag geschrieben und mit den jeweiligen Ereignissen , etc. verknüpft. Im folgenden Beispiel nimmt ein Panel-Control ein helleres Blau und eine kleinere Größe an, wenn man darauf klickt: Animiertes Element
96
Extender
Abb. 5.13: Das Element schrumpft und verliert Farbe
Eine vollständige Übersicht über die sehr umfangreichen Animationsfähigkeiten erhalten Sie unter http://ajax.asp.net/ajaxtoolkit/ Walkthrough/AnimationReference.aspx.
schnell + kompakt
97
5 – Control Toolkit
Hinweis Neben dem Vergrößern-Effekt und der Animation gibt es wie schon erwähnt eine Reihe weiterer Effekte. DropShadow erzeugt einen Schlagschatten, das recht neue SlideShow-Control zeigt Bilder und erlaubt die Navigation zwischen ihnen. Animiert wird auch mit UpdatePanelAnimation.
98
KAPITEL 6 Futures und Sonstiges 6.1
XML-Script
101
6.2
Drag&Drop
103
6.3
Animationen
112
Die Microsoft ASP.NET Futures sind – man möge den Ausdruck verzeihen – eine Restesammlung. Dort finden sich Funktionen, die es nicht mehr in die Final geschafft haben oder die ausrangiert wurden. Seit Mai 2007 wurden die Futures mit den ASP.NET Futures gebündelt und als gemeinsames DownloadPaket angeboten. Dadurch wurde die Restesammlung wirklich zu einer Art Vorschau. Allerdings ist bei den Ajax-Funktionen noch nicht klar, was in eine zukünftige Ajax-Version gelangen könnte. Aktuell enthalten sie allerdings nicht nur Fortschrittliches, sondern auch beispielsweise die XML-Script-Unterstützung, die noch Teil von der Entwicklungsversion Atlas war. Außerdem sind dort Drag&Drop-Unterstützung und Animationsmöglichkeiten mit clientseitiger Programmiermöglichkeit enthalten. Diese Funktionen sind etwas flexibler als die entsprechenden Controls im Control Toolkit. Basis des Ajax-Teils in den Futures ist eine DLL, Microsoft.Web.Preview.dll. Wenn Sie die Futures installiert haben, steht eine eigene Website-Vorlage zur Verfügung, die diese DLL gleich enthält. Sie heißt ASP.NET Futures Ajax Web Site – nicht
schnell + kompakt
99
6 – Futures und Sonstiges
zu verwechseln mit der ASP.NET Futures Web Site, die andere neue Produktfunktionen für ASP.NET enthält. Anderenfalls können Sie sie auch nachträglich in Ihren Bin-Ordner kopieren.
Abb. 6.1: Eine neue Futures Ajax-Website
Um die Futures-Funktionen in der Seite nutzen zu können, müssen Sie im ScriptManager die entsprechenden Skripte einbinden:
100
XML-Script
Verfügbar sind unter anderem die folgenden Skriptdateien: 쐌 PreviewScript für XML-Script-Unterstützung und die Basisfunktionalität 쐌 PreviewDragDrop für Drag&Drop-Unterstützung 쐌 PreviewGlitz für Animationen Daneben gibt es noch Funktionen für WebParts und beispielsweise eine Web-Services-Bridge. In den nächsten Abschnitten konzentrieren wir uns aber auf die hier vorgestellten Funktionen und vergleichen sie jeweils, soweit relevant, kurz mit den Möglichkeiten des Control Toolkit.
6.1 XML-Script XML-Script ist eine clientseitige XML-Sprache, mit der man Controls ansprechen und steuern kann. Der Plan von Microsoft war ursprünglich, das deklarative Entwicklungsmodell, das in ASP.NET serverseitig sehr gut funktioniert, auf die clientseitige Entwicklung zu übertragen. Allerdings wird das Coding recht komplex und alle Elemente müssen entsprechend in JavaScript gekapselt sein. Dass dies schwierig wird, sieht man schon an einem einfachen Label. In den Futures ist die XML-Script-Unterstützung dafür vorhanden. Allerdings gibt es nur zwei Eigenschaften in Sys.Preview.UI.Label, die setzbar sind: text für den Inhalt und htmlEncode für die Umwandlung von HTML-Sonderzeichen wie spitze Klammern. Ansonsten sind für XML-Script noch Controls und ein paar wenige andere Elemente aus den Futures möglich, z.B. Sys.Preview.UI.Button. Das folgende Beispiel nützt beide Eigenschaften und gibt ein wenig Text mit entsprechender Umwandlung aus. Zuerst müssen Sie das entsprechende Skript einbinden:
schnell + kompakt
101
6 – Futures und Sonstiges
Anschließend folgen die Elemente und das XML-Script:
102
Drag&Drop
Abb. 6.2: Per XML-Skript wird Text und Kodierung gesetzt
Hinweis Sollten Sie noch ältere Atlas-Beispiele besitzen, können Sie sie eventuell mit der XML-Script-Erweiterung des Future zum Laufen bringen. Insgesamt ist XML-Script aber nicht die Zukunft.
6.2 Drag&Drop In Sachen Drag&Drop bietet Microsoft ASP.NET Ajax diverse Funktionen: 쐌 Den DragPanelExtender im Control Toolkit. Dieses Control macht ein beliebiges Element ziehbar. 쐌 ReorderList im Control Toolkit. Diese Elemente sorgen für per Drag&Drop sortierbare Listen. Hinweis Im Control Toolkit verwenden außerdem einige andere Elemente wie der Slider, ein Schieberegler, Grundzüge von Drag&Drop.
schnell + kompakt
103
6 – Futures und Sonstiges
쐌 Den DragDropManager in den Futures. Hierbei handelt es sich um eine Drag&Drop-Schnittstelle, die sich an alte MicrosoftImplementierungen für Drag&Drop anlehnt. Sie wird auch im DraggableListItemExtender verwendet – allerdings ist sie dort als abgewandelte Kopie integriert, um das Control Toolkit nicht von den Futures abhängig zu machen. 쐌 Die Implementierung DragDropList in den Futures, die auf dem DragDropManager aufsetzt Sehen Sie sich die verschiedenen Alternativen einmal an. Der DragPanelExtender macht ein beliebiges Element ziehbar: Kasten
Die notwendigen Angaben sind das zu ziehende Element (TargetControlID) und der Anfasser, an dem gezogen wird (DragHandleID). Der Einfachheit halber ist das hier dasselbe Element. Drag&Drop klappt nur im Inhaltsbereich der Seite, sprich an Stellen, an denen sich Inhalt befindet. Außerhalb landet das Element wieder am Ausgangspunkt. Vor allem beim Testen kann das verwirren, weil das gezogene Element oft das einzige auf der Seite ist. Das Beispiel im Control Toolkit verwendet dafür einen kleinen JavaScript-Fix, der die Höhe des body-Bereichs setzt und auch auf Fenstergrößenänderungen reagiert:
104
Drag&Drop
function setBodyHeightToContentHeight() { document.body.style.height = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight)+"px"; } setBodyHeightToContentHeight(); $addHandler(window, "resize", setBodyHeightToContentHeight);
Hinweis Die Koordinaten für das jeweilige Element lassen sich – wie bei jeder Drag&Drop-Operation – natürlich auch z.B. über die Profile speichern. So bleibt für Nutzer auch nach dem Neuladen die ursprüngliche Position erhalten.
Abb. 6.3: Das Element wird gezogen
schnell + kompakt
105
6 – Futures und Sonstiges
Etwas aufwändiger sind per Drag&Drop sortierbare Listen. Hierfür gibt es das ReorderList-Element. Ähnlich wie das Accordion aus dem letzten Kapitel ist es ein unabhängiges Control, erweitert also nichts. Das Element verwendet eine Datenquelle, um Inhalte aufzunehmen. Wie die Ausgabe aussehen soll, wird dann über Templates gespeichert, z.B. ein für die Elemente. Das folgende Beispiel verwendet eine einfache XML-Datenquelle, um eine sortierbare Liste anzuzeigen: Erstes Element Zweites Element
Die XmlDataSource ist für die ReorderList an sich nur bedingt geeignet, da sie nur lesbar ist. Hier reicht sie allerdings zur Schilderung der Grundfunktion. Sie müssen in der ReorderList eine Datenquelle angeben. Außerdem benötigen Sie das zentrale Datenfeld und das Feld für die Sortierung. Beide sind in unserem Fall Eigenschaften in Elementen der ersten Ebene, da diese von der XmlDataSource zur Verfügung gestellt werden. Der eigentliche Inhalt wird dann im über einen XPath-Ausdruck geladen:
106
Drag&Drop
Abb. 6.4: Die Liste ist per Drag&Drop sortierbar
In den Futures von Microsoft ASP.NET (Ajax) gibt es nicht nur den DragDropManager als Grundlage für eigene Anpassungen, sondern die vollständig nutzbaren Implementierungen DragDropList und DraggableListItem. Mit DragDropList machen Sie ein Element, z.B. ein -Element, zu einem Ziel, in das die DraggableListItem-Elemente gezogen werden können. Außerdem lassen sich diese Elemente innerhalb der Liste verschieben. Die Liste selbst ist also quasi das Ziel für alle DraggableListItemElemente. Dementsprechend können Sie auch mehrere Listen in
schnell + kompakt
107
6 – Futures und Sonstiges
Spalten- oder Reihenform wählen und zwischen ihnen Elemente austauschen. Im folgenden Beispiel sollen zwei Reihen zum Einsatz kommen. Zur Vorbereitung steht erst eimal ein wenig HTML- und CSSArbeit an. Zuerst benötigen Sie zwei sogenannte Templates, eines für den Zielbereich (hier release genannt) und eines für eine leere Liste. Beim Zielbereich soll sich in unserem Fall die Hintergrundfarbe ändern, damit der Nutzer weiß, dass er hier die Maustaste loslassen darf. Damit das Ganze in Reihe angeordnet wird, ergänzen Sie noch ein float: left. Wollten Sie eine vertikale Liste, müssten Sie das weglassen. Leere Liste
Die eigentlichen Listen sind hier jeweils 600 Pixel breit und ein wenig voneinander entfernt. Die erste enthält standardmäßig zwei Elemente, die zweite drei. Die Elemente sind in diesem Beispiel nur so breit, dass drei nebeneinander in eine Liste passen würden. Sie werden auch mit float: left horizontal angeordnet: Drag & Drop 1 Drag & Drop 2
108
Drag&Drop
Drag & Drop 3
Anschließend werden beim Laden der Seite in der Methode pageLoad() die Listen und alle Elemente initalisiert. Für die Liste zuständig ist Sys.Preview.UI.DragDropList(Element). Als Einstellungen definieren Sie noch, wie und was gezogen wird. Außerdem müssen Sie die Richtung einstellen: function pageLoad() { var DropZone1 = new Sys.Preview.UI.DragDropList($get('liste1')); DropZone1.set_dragDataType("HTML"); DropZone1.set_acceptedDataTypes(["HTML"]); DropZone1.set_dragMode(Sys.Preview.UI.DragMode.Move); DropZone1.set_direction (Sys.Preview.UI.RepeatDirection.Horizontal);
Anschließend folgen die zwei Templates, die der Liste zugewiesen werden. Mit der Methode initialize() wird die Liste schließlich in Betrieb genommen: var dcTemplate = new Sys.Preview.UI.Template($get("release"), $get("release")); var lTemplate = new Sys.Preview.UI.Template($get("leer"), $get("leer"));
schnell + kompakt
109
6 – Futures und Sonstiges
DropZone1.set_dropCueTemplate(dcTemplate); DropZone1.set_emptyTemplate(lTemplate); DropZone1.initialize();
Für die zweite Liste verfahren Sie analog. Die zwei Templates können allerdings wiederverwertet werden: var DropZone2 = new Sys.Preview.UI.DragDropList($get('liste2')); DropZone2.set_dragDataType("HTML"); DropZone2.set_acceptedDataTypes(["HTML"]); DropZone2.set_dragMode(Sys.Preview.UI.DragMode.Move); DropZone2.set_direction(Sys.Preview.UI.RepeatDirection .Horizontal); DropZone2.set_dropCueTemplate(dcTemplate); DropZone2.set_emptyTemplate(lTemplate); DropZone2.initialize();
Nun geht es an die Elemente. Hierfür ist Sys.Preview.UI.DraggableListItem(Element) zuständig. Sie können außerdem mit set_ handle(Element) noch einen Anfasser für das Drag&Drop verwenden, z.B. eine Leiste über dem Inhalt. Der Einfachheit halber entspricht in diesem Beispiel der Anfasser dem Element, das ganze Element ist also ziehbar. Mit initialize() übernehmen Sie dann das Element. var ele1 = new Sys.Preview.UI.DraggableListItem($get('ele1')); ele1.set_handle($get('ele1')); ele1.initialize();
Das Vorgehen wiederholen Sie nun für die anderen zwei Elemente:
110
Drag&Drop
var ele2 = new Sys.Preview.UI.DraggableListItem($get('ele2')); ele2.set_handle($get('ele2')); ele2.initialize(); var ele3 = new Sys.Preview.UI.DraggableListItem($get('ele3')); ele3.set_handle($get('ele3')); ele3.initialize(); }
Abb. 6.5: Elemente sind innerhalb und außerhalb der „Listen“ verschiebbar
schnell + kompakt
111
6 – Futures und Sonstiges
Profitipp Der große Vorteil am Drag&Drop über die Listenfunktion in den Futures ist, dass Sie alle Einstellungen per JavaScript vornehmen können und so die Möglichkeit haben, beliebige Elemente dynamisch zu generieren und per JavaScript zu steuern.
6.3 Animationen Für Animationen haben Sie im letzten Kapitel bereits das Animation-Control kennengelernt. Allerdings gibt es auch in den Futures Animationsmöglichkeiten. Die Bandbreite geht von der Transparenzanimation bis zur Animation beliebiger Attributwerte (NumberAnimation). Außerdem gibt es aus anderen Animationen zusammengesetzte Kompositionen (CompositeAnimation). Um die Funktionen zu nutzen, müssen Sie PreviewGlitz einbinden. PreviewScript ist hier für den später eingesetzten Timer notwendig:
Das folgende Beispiel verwendet eine Aus- und Einblendeanimation (FadeAnimation) und kombiniert sie noch mit einem Timer, um die Animationen zeitgesteuert aufzurufen. Das Zielobjekt der Animation ist ein einfaches Panel: Inhalt des Panel
112
Animationen
Beim Laden der Seite wird es mit einer FadeAnimation ausgeblendet. Dazu müssen Sie zuerst auf das Element zugreifen. Es muss ein Control sein. Das Control kann per Sys.UI.Control(), also Ajax Extension-Funktionalität, definiert werden. Alternativ gibt es auch noch einige spezielle Controls in den Futures. Im Abschnitt zu XML-Script haben Sie beispielsweise Sys.Preview.UI.Label() kennengelernt. Den Effekt, also das Ausblenden, steuern Sie über set_effect(). Die Dauer steuern Sie mit set_duration(Sekunden). Der Wert ist ein Wert in Sekunden. Wollen Sie kleinere Einheiten, verwenden Sie einfach Dezimalzahlen mit Punkt als Trennzeichen. Mit play() wird die Animation dann abgespielt. var control = null; function pageLoad() { control = new Sys.UI.Control($get('Panel1')); var ani = new Sys.Preview.UI.Effects.FadeAnimation(); ani.set_target(control); ani.set_effect(Sys.Preview.UI.Effects.FadeEffect.FadeOut); ani.set_duration(4); ani.play(); var timer = new Sys.Preview.Timer(); timer.set_enabled(true); timer.set_interval(6000); timer.add_tick(fadeIn); timer.initialize(); }
Der Timer basiert auf der Klasse Sys.Preview.Timer(). Er erhält mit set_interval(Millisekunden) ein Intervall in Millisekunden. Das heißt in diesem Beispiel, das Einblenden startet zwei Sekunden nach dem Ausblenden. Mit add_tick(Funktion) wird ein Event-Handler registriert, der jedes Mal aufgerufen wird, wenn die Intervallzeit erreicht ist. Gestartet wird der Timer mit initialize().
schnell + kompakt
113
6 – Futures und Sonstiges
Eine Referenz auf den Timer wird an die aufgerufene Funktion übergeben. Sie können mit set_enabled(false) den Timer wieder ausschalten und so verhindern, dass die Einblendanimation immer wieder gezeigt wird. Die Einblendanimation entspricht weitgehend der Ausblendanimation, nur dass als Effekt FadeIn verwendet wird: function fadeIn(sender) { var ani = new Sys.Preview.UI.Effects.FadeAnimation(); ani.set_target(control); ani.set_effect(Sys.Preview.UI.Effects.FadeEffect.FadeIn); ani.set_duration(6); ani.play(); sender.set_enabled(false); }
Abb. 6.6: Das Element verschwindet
114
Stichwortverzeichnis
abortPostback() 31 Accordion 86
AccordionPane 86 add_initializeRequest() 31 add_tick() 113 addComponent() 46 addCssClass() 45 Ajax Dokumenation 12 Einrichtung 12 Homepage 10 JavaScript-API 39 Ajax.NET Professional 10 AjaxControlToolkit.sln 81 Aktualisierung 29 alert() (JavaScript) 93 allowAnonymous (Attribut) 77 Always (Wert) 22 Animationen 95, 112 AnimationExtender 96 Anonyme Profile 77 append() 51 appendLine() 51 Application 46 Architektur 19 Array 48 ASP.NET Konfiguration 67 ASP.NET 2.0 Ajax Extensions 1.0 11 ASP.NET Ajax Control Toolkit 11 ASP.NET Ajax Futures 11 ASP.NET Ajax-Enabled Web Site 18 Assembly 83 AssociatedUpdatePanelID (Attribut) 27
schnell + kompakt
115
$addHandler() 42, 58 $addHandlers() 44 $clearHandlers() 44 $find() 46 $get() 40 $removeHandler() 44 96