.comment-link {margin-left:.6em;}

Verbindungen zwischen Controls

Das Trennen und Einkapseln von Funktionalität in Komponenten hilf sehr dazu ein wieder verwendbares Framework aufzubauen. Die meisten Komponenten existieren aber nicht für sich alleine sondern müssen an andere Komponenten angebunden werden.

Der klassische Ansatz

Wenn man die Standard Controls von ASP.NET verwendet benutzt man die serverseitigen Ereignisse der Controls, Schaltflächen, Felder und der Seite und man schreibt kleine Methoden die auf diese Events reagieren. Innerhalb dieser Ereignis Funktionen referenziert man die anderen Objekte direkt, da sie ein Teil der Seite oder der Control Klasse sind über ihre id oder zur Laufzeit über eine Such Methode.

Diese Ereignis Funktionen werden ausgeführt da ein submit() der HTML Form ausgeführt wird; eine Situation die in AJAX Applikationen nicht vorkommen sollte. Aus diesem Grund benötigt man eine Verbindung auf dem Client Anteil der Applikation in JavaScript.

Man kann den Ansatz, der vom Server her bekannt ist, auch auf dem Client implementieren indem man Event Funktionen für die HTML Ereignisse der HTML Objekte anbindet.

Der Nachteil dieser Architektur ist dass bei komplexen controls die HTML Objekte, die die Ereignisse zur Verfügung stellen eventuell innere HTML Objekte eines Controls sind, ohne eigene feste id oder auch nicht einmal vorhanden, wenn die Seite geladen wird.

Wenn man diesem Ansatz folgen will kann man die Metode jcl.AttachEvent verwendet, Diese Methode aus dem jcl.js Include file kann man dafür benutzen. Sie funktioniert auch auf den verschiedenen Browser Plattformen und erlaubt mehrere gleichzeitige Ereignis Registrierungen.

Selbst wenn man alle inneren Details eines Controls kennt möchte man dieses Wissen nicht außerhalb verwenden denn man gibt damit die Chance auf das Control zu re-implementieren ohne die Implementierungen der Seiten ebenfalls ändern zu müssen.

Der Web-Part Ansatz

Mit Sharepoint und den ASP.NET 2.0 WebPart Framework kam ein anderer Mechanismus um Komponenten zu verbinden indem ein "Provider-Subsription" Pattern verwendet wird. Komponenten können sich selbst registrieren um Änderungen von Werten von Eigenschaften zu veröffentlichen (Provider) oder zu konsumieren (Subscription). Jedes mal, wenn eine Eigenschaft über einen Provider ihren Wert ändert werden alle Subscibers über diese Änderung informiert.

Mit diesem Ansatz ergeben sich einige Vorteile:

  • Der Mechanismus funktioniert sogar, wenn die Controls auf der Seite zur Compiler-Zeit nicht bekannt sind. (Sharepoint)
  • Mehrere Controls können auf einfach Art die gleiche Eigenschaft veröffentlichen.
  • Mehrere Controls können einfach die gleiche Eigenschaft konsumieren.
  • Man benötigt die Browser spezifischen Events nicht.
  • Die IDs der Objekte müssen nicht bekannt sein.

Wie man passt ist dieser Ansatz auf einem höheren Niveau besser zu dem Problembereich der Komponenten basierten Entwicklung von Seiten und Portalen und kann des weiteren auch mit dem Event-Modell der HTML Objekte kombiniert werden.

Das Beispiel zu Verbindungen

Das Beispiel benutzt 4 unterschiedliche Arten von Controls die mit in JavaScript Behaviours implementiert sind um aufzuzeigen (und zu testen) wie die clientseitlige Implementierung und Verwendung von Verbindungen funktioniert. Es gibt 3 Eigenschaften auf der Seite (x, y und z) die mit 2 unterschiedlichen Controls verändert werden können und die zusätzlich mit einem einfachen Bar-Chart angezeigt werden.

Ein weiteres Control protokolliert alle Änderungen der Eigenschaften.

See: http://www.mathertel.de/AJAXEngine/S03_AJAXControls/ConnectionsTestPage.aspx

PropInput Control

Diese Control erzeugt ein HTML input Element das mit einem JavaScript Behaviour erweitert wurde um die Änderungen des Wertes als Änderung einer Eigenschaft weiterzugeben.

Der Name der Eigenschaft wird durch das name-Attribut des Controls festgelegt.

Dieses Control registriert sich selbst auch als Subscriber um den aktuellen wert anzuzeigen, wenn er von einem anderen Control aus verändert wurde.

PropHSlider

Dieses Control implementiert ein horizontal verschiebbares Rechteck das als Schieber verwendet wird um eine Eigenschaft im Bereich von 0 bis 100 zu ändern.

Der Name der Eigenschaft wird durch das name-Attribut des Controls festgelegt.

Dieses Control registriert sich selbst auch als Subscriber um den aktuellen Wert anzuzeigen, wenn er von einem anderen Control aus verändert wurde.

PropBarChart

Diese Control implementiert ein einfaches Balkendiagramm, um mehrere Werte anzuzeigen. Die Namen der Properties werden unter den Balken angezeigt.

Die Namen der Properties können durch das Attribut "Properties" angegeben werden, indem man eine durch Semikolon getrennte Liste von Namen verwendet. Die maximale darstellbare Zahl kann durch das "maxvalue" Attribut spezifiziert werden. Dieser Wert wird als Skalierungsfaktor für die Anzeige verwendet.

PropEventLog

Dieses Control protokolliert jede Änderung einer Property property und zeigt den neuen Wert auf der Seite an.

DataConnections Reference

Die Namen der Properties werden von den DataConnections Funktionen immer in Kleinbuchstaben konvertiert und müssen deshalb vor Vergleichen mit anderen Namen ebenfalls immer in immer Kleinbuchstaben verglichen werden.

DataConnections.RegisterProvider(obj, propName)

Ein Objekt, das eine Property publiziert, muss sich mit dieser Funktion registrieren.

Der Name der Eigenschaft kann als '*' angegeben werden, um das Objekt für alle existierende Eigenschaften zu registrieren.

DataConnections.RegisterConsumer(obj, propName)

Ein Objekt, das über eine Property Änderung informiert werden soll, muss sich mit dieser Funktion registrieren.

Der Name der Eigenschaft kann als '*' angegeben werden, um das Objekt für alle existierende Eigenschaften zu registrieren.

DataConnections.Raise(propName, propValue)

Diese Funktion muss aufgerufen werden um die Änderung einer Eigenschaft bekant zu geben. Bei allen für diese Eigenschaft registrierten Objekten wird die GetValue Funktion sofort aufgerufen.

DataConnections.GetPropValue(propName)

Diese Funktion kann benutzt werden um den aktuellen Wert einer Eigenschaft abzufragen. Damit ist es nicht mehr notwendig dass sich mehrere Controls sich die aktuellen Werte merken müssen.

DataConnections.PersistPropValue(propName)

Mit dieser Funktion kann eine Property in einem Cookie zwischengespeichert werden und wird beim nächsten Betreten der Seite wieder auf diesen Wert gesetzt. Das hilft dabei das erneute Laden von Seiten zu überleben.

Das verwendete Cookie ist nicht permanent so dass der Wert nicht mehr verfügbar ist nachdem der Browser geschlossen wurde.

control.GetValue(propName, propValue)

Diese Funktion muss von den Objekten implementiert werden die über Änderungen des Wertes von Eigenschaften informiert werden wollen.

Aufbau eines AJAX Controls

Ein AJAX fähiges Control (kurz AJAX Control) zu schreiben ist so einfach wie eine andere AJAX fähige web Applikation zu schreiben. Der einzige Unterschied liegt darin wie HTML, JavaScript und der verbindende Kram wie z.B. AJAX Actions und die Aufrufe auf den Server an die richtigen Stellen verteilt werden so dass das Control an anderen Stellen wieder verwendet werden kann.

Wenn es nur darum geht einen Anteil der Applikation so aufzutrennen dass andere Mitarbeiter des Teams an ihnen unabhängig arbeiten können ist es möglich den ganzen Code in eine einzige *.ascx Datei eines User Controls zu schreiben.

Mit der Technik der JavaScript Behaviours, die ich vor einigen Tagen veröffentlichte sollte man sich vertraut gemacht haben:

Ich beschreibe hier User Controls. Wenn man Web Controls verwendet funktioniert einiges anders.

Parameter

Parameter, mit denen die spezifische Funktionalität eines AJAX Controls angegeben wird ist ein Teil des Source-Codes indem man Attribute des Tags verwendet das für das Control steht:

<ajax:Lookup ... LookUpService="OrteLookup" ... />

Was man hier sieht ist NICHT HTML Code sondern eine deklarative Beschreibung für einen zu erstellenden HTML Code an dieser Stelle. Wenn man ASP.NET User Controls verwendet werden diese Attribute nicht automatisch in HTML Attribute umgewandelt. Anstatt dessen bildet das ASP.NET Framework diese auf die Klasse ab, die für das Control auf dem Server angelegt wird. Jedes Attribut das als Parameter verwendet werden soll muss also als Feld oder Eigenschaft der Klasse des Controls definiert sein um den Wert des Attributes auf dem Server verfügbar zu haben.

<%@ Control Language="C#" ... %>
<script runat="server">
  public string lookupservice = "DefaultService.asmx";
  ...
</script>

Um den Wert nun auf dem Client zur Verfügung zu haben müssen diese im HTML code, der durch das Control entsteht mit hinaus geschrieben werden:

<input ... lookupservice="<%=this.lookupservice %>" ... />

Die Konsequenz davon ist, dass die Defaultwerte für Parameter, die nicht im Source Code angegeben werden in den Initialisierungen der Felder oder Eigenschaften angegeben werden müssen. Die Werte in den JavaScript Behaviour Prototypen werden dadurch immer überschrieben.

HTML Code

Den spezifischen HTML Code des User Controls kann man einfach am Ende des *.ascx Files hinschreiben. Er kann so komplex werden wie es eben sein muss.

Es ist wichtig das auch die einndeutige id des Controls im HTM Code enthalten ist:

id="<%=this.UniqueID %>"

Ein ASP.NET User Control erzeugt nicht automatisch ein äußeres HTML Objekt. Es ist auch möglich mehrere Objekte hintereinander zu erzeugen. In diesem Fall wird das JavaScript Behaviour an das Objekt gebunden das die eindeutige id mitbekommen hat.

Wenn man eine Referenz auf eine andere Web Ressource benötigt kann man die Methode ResolveUrl des Page Objektes verwenden.

src="<%=Page.ResolveUrl("~/controls/images/drop.gif") %>"

Die Programmierung des Behaviours

Das JavaScript Behaviour mit dem die clientseitige Funktionalität des User Controls implementiert wird sollte in einer eigenen JavaScript Include Dateien implementiert werden. Das ist zwar streng genommen nicht notwendig aber es ist gut für die allgemeine Performance, denn der Browser kann dieses so im Cache speichern.

Ich verwende für diese spezifischen Include Dateien den selben Namen wie für das *.ascx File und sie liegen ebenfalls in ~/controls Ordner.

Um das Behaviour an das html Objekt zu binden wir ein kleines javaScript Fragment benötigt, das ebenfalls Bestandteil des generierten HTML Codes ist:

<script defer="defer" type="text/javascript">
  jcl.LoadBehaviour("<%=this.UniqueID %>", LookUpBehaviour);
</script>

AJAX Actions

Die AJAX Aktion, die vom Control verwendet wird kann als Bestandteil des Protoyp Objektes des Behaviours deklariert werden . Im LookUp Control findet man dazu die _fillAction Eigenschaft mit der die AJAX Aktion deklariert wurde.

// declare an AJAX action to the lookup service
_fillAction: {
  delay: 100,
  prepare: function(fld) { fld.savevalue = fld.value; return (fld.value); },
  call: null, // is assigned later
  finish: function (val, fld) {
    if (fld.savevalue != fld.value) {
      ajax.Start(fld._fillAction, fld); // again
    } else {
      var dd = fld.CreateDropdown(fld);
      fld.FillDropdown(dd, val);
    } // if
  }, // finish
  onException: proxies.alertException
}, // _fillAction

Wenn man nur eine einzige Instanz des Controls auf einer Seite hat wird man damit keine Probleme haben. Wenn es mehrere Instanzen des gleichen Controls auf einer Seite gibt werden diese Definitionen von allen Controls gemeinsam genutzt so dass es besser ist mit der jcl.CloneObject Funktion eine Kopie zu erzeugen, denn die Contols werden unterschiedliche WebServices verwenden.

Die Referenz auf den WebService sollte ebenfalls erst in der init Funktion gesetzt werden nachdem die Seite komplett geladen wurde da es nicht gesichert ist, dass die WebService proxies bereits vollständig verfügbar sind, wenn das Behaviour angebunden wird.

this._fillAction = jcl.CloneObject(this._fillAction);
this._fillAction.call = proxies[this.lookupservice].GetPrefixedEntries;

Registrieren Der Script Include Dateien

Bevor Der HTML Text An Den Client Geschickt Wird Müssen Alle Javascript Include Dateien Auf Der Seite Registriert Werden. Das Kann In Der OnPreRender Methode geschehen:

protected override void OnPreRender(EventArgs e) {
  base.OnPreRender(e);

  ...

  // register the JavaScripts includes without need for a Form.
  if (!Page.ClientScript.IsClientScriptBlockRegistered(Page.GetType(), "CommonBehaviour")) {
    Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "CommonBehaviour", String.Empty);
    ((HtmlHead)Page.Header).Controls.Add(new LiteralControl("<script type='text/javascript' src='"
      + Page.ResolveUrl("~/controls/jcl.js")
      + "'><" + "/script>\n"));
  } // if

  if (!Page.ClientScript.IsClientScriptBlockRegistered(this.GetType(), "MyBehaviour")) {
    Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "MyBehaviour", String.Empty);
    ((HtmlHead)Page.Header).Controls.Add(new LiteralControl("<script type='text/javascript' src='"
      + Page.ResolveUrl("~/controls/LookUp.js")
      + "'><" + "/script>\n"));
  } // if
} // OnPreRender

Die Quellcode Fragmente kann man in dem dritten Teil der Beispiele finden:

OrteLookUp.aspx ist die Implementierung der Seite

~/controls/LookUp.ascx ist das erste sichtbare Control

~/controls/LookUp.js ist das JavaScript Behaviour dazu.

AJAX Engine Dokumentations Update

Ich habe heute die Dokumentation der AJAX Engine aktualisiert.

See http://www.mathertel.de/AJAX/Aspects%20of%20AJAX_index.htm.

Jetzt ist es nicht mehr notwendig wie im Blog vom Ende nach vorne lesen zu müssen, da die Artikel ja teilweise aufeinander aufbauen.

ATLAS

Das AJAX Framework von Microsoft mit den Namen ATLAS wurde gestern veröffentlicht. Ich sehe es gerne, dass Microsoft meiner Idee folgt und Proxies in JavaScript zu den WebServices generiert.

Sie verwenden für die Kommunikation eine JSON Syntax, nicht SOAP oder WSDL so dass der Client nicht sehr portabel zu anderen WebService Servern zu sein scheint.

Verwenden von ASP.NET

Mit der Verwendung von ASP.NET auf dem Server wird Einiges einfacher da damit ein Framework für das mehrfache verwenden von HTML Code-Fragmenten, für die Erstellung von Controls und Komponenten sowie einige weitere nützliche Dinge zur Verfügung steht. Einige der Möglichkeiten des Seitenmodells, der User Controls und der Web Controls werden benutzt um AJAX Controls einfach bauen zu können.

Zusammen mit den JavaScript Behaviors über die ich bereits schrieb und mit denen der clientseitige Teil realisiert ist bieten die ASP.NET Controls auf dem Server eine solide Grundlage für AJAX Controls.

Es gibt einige gute Artikel und Beispiele auf dem Web die erklären wie man solche Controls realisiert aber es gibt auch einige trickreiche Dinge zu beachten um diese Controls als AJAX Controls zu verwenden.

User Controls

Eine sehr brauchbare Funktionalität der ASP.NET User Controls besteht darin den mehrfach benötigten HTML Code nur einmal in einer *.ascx Datei zu schreiben und dann so oft wie nötig wieder zu verwenden indem referenzierende Tags in die ASP.NET Seiten aufgenommen werden.

Web Controls

Einige Dinge können mit User Controls nur schwer realisiert werden. Insbesondere wenn das Control nur einen Rahmen für weitere innere HTML Objekte bildet können User Controls nicht verwendet werden. In diesen Fällen sind WebControls, die als spezielle Klassen realisiert werden müssen, leichter zu implementieren und so findet man beide Technologien in den Beispielen.

Kein Form Element

AJAX Controls werden realisiert damit KEIN Rückübertragen (postback) der Änderungen des Benutzers auf den Server und ein neues Laden der Seite mehr stattfinden. Deswegen wollen wir AJAX in unseren Web Applikationen. Im Gegensatz dazu wurden ASP.NET Controls genau für diese Art der Interaktion gemacht und werden deshalb meistens innerhalb eines HTML Form Elementes platziert. Da wir aber weder "autopostback" Funktionalitäten noch direkt ein direktes "form.submit()" verwenden werden haben wir keine Probleme damit die AJAX Controls innerhalb eines HTML form Element zu platzieren.

Wenn Sie planen existierende ASP.NET Web Forms mit AJAX Controls zu erweitern –eine Situation die ich unterstützen will – wird das HTML Form Element benötigt. Wenn neue Web Seiten ohne die serverseitige ASP.NET Web Form Funktionalität aufgebaut werden kann auf dieses HTML form Element komplett verzichtet werden.

Die Eingabe Taste

Etwas wird Benutzer stören, wenn ein Form Element vorhanden ist: Wenn man in einem Eingabefeld die Eingabe oder Enter Taste drückt wird (wie auch bei F5) die komplette Seite neu geladen. Alle Informationen die seit dem die Seite geladen wurde und durch asynchrone Aufrufe oder durch Eingaben des Benutzer auf die Seite kamen gehen dadurch verloren.

Die Eingabe oder Enter Taste hat im Gegensatz dazu keinen sichtbaren Effekt bei Input Feldern außerhalb eines Form Elementes da der Zeilenumbruch nicht dem Wert des Feldes hinzugefügt wird.

In der jcl.js Datei ist ein einfacher Trick implementiert, der dabei hilft um diese Situation herum zu kommen. Indem alle keypress Ereignisse abgefangen und überprüft werden ist es möglich das Ereignis frühzeitig abzubrechen und das automatische Abschicken des Formulars zu verhindern.

Um diesen Trick für HTML input Elemente zu aktivieren müssen dieses das Attribut "nosubmit" mit dem Wert "true" haben. Man kann dieses Attribut dem HTML Code oder dem JavaScript behaviour des AJAX Controls mitgeben.

Gemeinsames JavaScript

Die AJAX Controls verwenden die JavaScript behaviours und benötigen deshalb alle die gemeinsame Include Datei "~/controls/jcl.js ". Die moisten Controls benötigen auch jeweils eine weitere Inlcude Datei um den spezifischen Teil des JavaScript behaviours in der Form des Prototyp Objektes einzubinden.

Registrieren von Script-Includes

Eine sehr nützliche serverseitige Funktionalität von ASP.NET Web Forms ist die Art wie Controls kontrollieren können welche JavaScript Include Dateien notwendig sind damit ein Control richtig arbeiten kann. Die Funktion " RegisterClientScriptBlock" die im Page Objekt verfügbar ist als auch das neue Page.ClientScriptManager Objekt von ASP.NET 2.0 können verwendet werden um HTML Code anzugeben der vor dem weiteren Code einer HTML Form an den Client geschickt wird.

Mit "IsClientScriptBlockRegistered" ist es möglich zu prüfen, ob bereits ein entsprechender Script Block an den Client unterwegs ist.

Dieser Mechanismus ist perfekt geeignet um AJAX Controls zu bauen, da der Programmierer nichts darüber wissen muss, welches spezifisches JavaScript include file auf den Client gesendet werden muss, damit ein bestimmtes Control auch funktionieren kann. Er muss nur das Control an der richtigen Stelle in den HTML Code einbringen und alles andere funktioniert wie es soll.

Page.RegisterClientScriptBlock("CommonBehaviour",
  "<script type='text/javascript' src='"
  + Page.ResolveUrl("~/controls/jcl.js ")
  + "'><" + "/script>\n"));

Wenn ein HTML Form Element auf der Seite gibt existiert wird der registrierte HTML Code vor dem weiteren Code der Form eingebunden.

Wenn man ASP.NET 1.1 verwenden will muss man ein HTML Form Element vor al dem anderen HTML Code in der Seite includieren, Das bedeutet nicht, dass man die AJAX Controls in dieses Element hineinsetzen muss. Sie können auch nach einem leeren Form Element positioniert werden.

Registrieren von Script-Includes

Wenn man ASP.NET 2.0 verwendet kann man mit einem klenen Trick dafür sorgen, dass die notwendigen Include Dateien innerhalb des HTML head Elementes das mit "runat=server" deklariert ist aufgenommen werden.

// register the JavaScripts includes without need for a HTML form.
if (!Page.ClientScript.IsClientScriptBlockRegistered(Page.GetType(), "CommonBehaviour")) {
  Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "CommonBehaviour", String.Empty);
  Page.Header.Controls.Add(new LiteralControl("<script type='text/javascript' src='"
    + Page.ResolveUrl("~/controls/jcl.js ")
    + "'><" + "/script>\n"));
} // if

Mit diesem Trick macht es keinen Unterschied ob ein HTML form Element vorhanden ist oder nicht.

Beispiele und Downloads

Es sind bereits einige Beispiele von AJAX Controls auf der Beispiel Web Site veröffentlicht. Ich habe eine Portal-Seite hinzugefügt und sie sind dort im Bereich [Samples] über den 3. Verweis zu finden.

Man kann auch das ganze Projekt – so wie es ist downloaden. Es ist für ASP.NET 2.0 Beta 2 gemacht aber es sollte auch mit den August Versionen funktionieren.

Caching mit AJAX Applikationen

AJAX Applikationen bieten bessere Antwortzeiten und sind (scheinbar) schneller als traditionelle Web Applikationen.

Der wesentliche Grund dafür liegt in der Trennung zwischen dem ersten Laden der Seite vom Nachladen zusätzlicher Daten sowie der Abwesenheit des wiederholten Ladens der Seite wenn sich Daten ändern.

Der erste Aufbau einer Seite funktioniert mit einem herkömmlichen Aufruf einer URL mit der Hilfe des http-get Mechanismus. Der Aufruf des Servers im Hintergrund mit der Hilfe von asynchronen XMLHttpRequests ist der zweite und mehrfach wiederholte Teil.

Caching kann bei beiden Arten des Aufrufs des Servers helfen und die beste Performance erreicht man, indem Aufrufe des Servers verhindert werden.

Caching des ersten Ladens einer Seite

Das Laden der Seite durch das Navigieren auf eine URL kann am effektivsten mit der Hilfe der clientseitigen Caching Funktionen des Browsers verbessert werden. Wenn die richtigen HTTP-Header mitgegeben werden fragt der Browser nicht mehr den Server nach neuen Versionen einer URL-Ressource und wird sich auf die im clientseitigen Cache gefundenen Daten verlassen. Einige Dinge sind dabei zu beachten damit dies richtig funktioniert.

Es gibt von Eric Lawrence ein sehr nützliches Werkzeug für Windows mit dem Namen fiddler: http://www.fiddlertool.com/. Er schrieb ebenfalls einen guten Artikel über Performance und das http Protokoll: http://www.fiddlertool.com/Fiddler/help/http/HTTPPerf.mht.

Ebenfalls lesenswert ist http://msdn.microsoft.com/library/default.asp?url=/workshop/author/perf/perftips.asp.

  • Beim ersten Laden der Site dürfen keine Daten oder Informationen vorhanden sein, die sich oft ändern oder auf dem Client sehr schnell nach Änderungen verfügbar sein müssen.
    Wenn Änderungen an diesen Daten durch einen Klick oder eine andere Aktion auf dem Client geändert werden ist es möglich ein erneutes Laden der Seite zu erzwingen, auch wenn die Caching-Zeit noch nicht abgelaufen ist. In diesem Fall kann man mit einer lang laufenden Caching Zeit und mit einer schnellen Änderung der Seite leben.
  • Die Seite muss so konstruiert werden, dass sie eine (fast) statische Ressource aus der Sicht des Clients darstellt.
    Es ist dennoch möglich, dass sie für unterschiedliche Benutzer abweicht. Wenn die personalisierte Version ausgeliefert wird, müssen in diesem Fall die Caching Funktionen des Servers als auch die der Proxy Server ausgeschaltet sein.
  • Je kleiner desto schneller.
    Ich rate nicht zu großen Grafiken oder umfangreichen inline Style Attributen. Die Google Applikationen zeigen, dass man schnelle Web Applikationen auch ohne viel Grafik bauen kann.
  • Verwenden von Include Dateien für JavaScript und CSS Dateien.
    Include Dateien können ebenfalls auf dem Client gecacht werden aber sie können auch von mehreren Seiten gemeinsam genutzt werden. Es ist gut Include Dateien für gemeinsame Funktionalitäten oder Styles zu nutzen. Seltene oder nur einmalig genutzte Include Dateien verlangsamen die Applikationen.
  • Nur Kleinbuchstaben in URLs
    Für Windows Anwender ist es nicht offensichtlich, dass "page.aspx" und "Page.aspx" zwei unterschiedliche Web Ressourcen sind. Auch wenn der Server (IIS und ASP.NET) diese gleich behandeln wird der Client sie zweimal vom Server holen und lokal speichern. Die Tatsache, die sie unterschiedlich macht ist die Schreibweise der Referezen in den "src" und "href" Attributen der HTML Tags.
    Da ich mir nie sicher bin wie eine Referenz an anderen Stellen geschrieben ist verwende ich gerne nur Kleinbuchstaben.
  • Verwenden der richtigen http-Headers.
    Für den IE existieren die 2 speziellen Caching attribute "pre-check" und "post-check" die korrekt gesetzt werden sollten so dass der IE garnicht nach einer neuen Version einer Siete fragt sondern still die Version der Ressource verwendet, die im Client-Cache liegt.

Caching der asynchronen Abfragen

Nachdem die Seite geladen ist gibt es mehrfache Anfragen auf den Server im Hintergrund mit der Hilfe des XmlHttpRequest Objektes.

Wenn lang laufende Methoden auf dem Server aufgerufen werden, wie z.B. komplexe SQL Abfragen oder teure Kalkulationen, ist es möglich den Server anzuweisen die Ergebnisse zu cachen und zurück zu liefern ohne die Methode mehrfach auszuführen.

In ASP.NET verwendet man die CacheDuration Eigenschaft des WebMethod Attributes um eine Anzahl der Sekunden anzugeben die ein Ergebnis im Cache des Servers verbleiben darf.

[WebMethod(CacheDuration=60)]

Ein einfaches Beispiel dafür kann man im folgenden Artikel finden: http://support.microsoft.com/default.aspx?scid=kb;en-us;318299

Der Vorteil dieser Vorgehensweise liegt darin, dass alle Clients sich diesen gemeinsamen Cache teilen und dass wenn mehrere Clients denselben Service aufrufen sehr gute Antwortzeiten erreicht werden.

Es ist auch möglich auf dem Client zu cachen. Diese Vorgehensweise führt zu weniger Netzwerkverkehr da der mehrfache Aufruf verhindert wird, http Header helfen in dieser Situation nicht es kein http-Get Aufruf ist und auch Nutzdaten im http-body enthalten sind. Caching muss deshalb mit der Hilfe einiger Scripts erfolgen.

Die Caching Funktionalitäten in der JavaScript WebService Proxy Implementierung kann mit der Hilfe der Methode proxies.EnableCache aktiviert werden. Dabei wird die Funktion übergeben für die das Caching verwendet werden soll. Das CalcFactorsAJAX.htm Beispiel hat jetzt eine Schaltfläche, die aufzeigt wie das geht:

proxies.EnableCache(proxies.CalcService.CalcPrimeFactors)

Auch das TableData.aspx Beispiel verwendet Caching und das mehrfache Holen des gleichen Datensatzes zu verhindern.

Durch den Aufruf dieser Methoden wird ein JavaScript Objekt hinzugefügt das alle Ergebnisse speichert und einen Aufruf verhindert wenn zu dem Parameter bereits ein Eintrag in diesem Objekt existiert.

Das ist keine perfekte Lösung aber sie funktioniert unter den folgenden Randbedingungen:

  • Der Parameter muss ein String oder eine Nummer sein die für das Indizieren von Eigenschaften in JavaScript Objekten verwendet werden kann.
  • Der Cache leert sich nicht von alleine. Er kann aber durch einen erneuten Aufruf von EnableCache geleert werden.
  • Es werden nur Methoden mit einem einzigen Parameter unterstützt.

Caching funktioniert gut in AJAX Applikationen und hilft die Antwortzeiten zu verbessern indem Ausführungen, Downloads und WebServer Aufrufe vermieden werden.

Project Site Update

Die letzte Woche war lang und ich schrieb viel Sourcecode und keinen Text. Ich habe jetzt die Projekt WebSite side http://www.mathertel.de/AJAXEngine/ aktualisiert und hoffe dass sie jetzt etwas brauchbarer ist. Ich habe ihr mehr Struktur gegeben und jetzt ist genug Platz um den nächsten Schritt zu starten.

  • Die Lizenzbedingungen unter denen diese Arbeit verfügbar ist habe ich geklärt und einen Link auf die Creative Commons Attribution 2.0 Germany License ergänzt. Jetzt ist es klar dass jeder diese Arbeit auch für kommerzielle Dinge verwenden kann. Bitte behaltet meinen Namen in den jeweiligen Lizenzbedingungen.
  • Die Beispiele aus der Zeit vor AJAX (erster Teil) habe ich von den AJAX Beispielen (zweiter Teil) getrennt.
  • Der dritte Teil wird sich mit wieder verwendbaren Komponenten – AJAX Controls – beschäftigen. Die ersten Beispiele sind bereits publiziert und wer neugierig ist kann sie suchen.
  • Ich habe ein Impressum der Seite hinzugefügt und man findet darin leicht meine E-Mail Adresse. Es ist ein GIF-File, damit die Spinnen (spiders) mich nicht zu leicht finden´.

Ich hoffe die Seite gefällt :-)

AJAX = Asynchronous JavaScript And XML (+ DHTML)

Über dieses Blog

XML

Die Programmierung im Ajax Stil ist eine interessante Art der Programmierung von Web Applikationen unter Verwendung der stabilen Internet Technologien wie HTML und Javascript. In diesem BLOG will ich meine Erfahrungen auf diesem Gebiet und einige interessante Aspekte mit einfachen wie auch fortgeschrittenen Themen beleuchten.

Downloads:

AjaxEngine.zip (39 kByte)

This Zip-File contains the core files of the AJAX engine and the AJAX controls.

Ajax.zip (164 kByte)

This Zip-File contains the ASP.NET 2.0 web project that builds this side. All samples are included.

Sample WebSite:

Die Beispiele sowie den ausführlichen Sourcecode findet man auf der Beispiel Website:
http://www.mathertel.de
/AjaxEngine/Default.aspx
.

Documentation:

See http://www.mathertel.de/AJAX

License

Creative Commons License
This work is licensed under a Creative Commons Attribution 2.0 Germany License.

Letzte Posts

Name: MatHertel
Standort: Germany

Impressum

Archiv

Powered by Blogger