11 December 2009 HowTo; AJAX; ASP.NET; JSON; JSONP oliver.guhr

image Eigentlich kann man Ajax Requests nur an Adressen senden die unter der gleichen Domain erreichbar sind wie die Seite auf der das Script ausgeführt wird. Der Grund dafür ist die Same Origin Policy in Javascript, diese besagt das der Port, das Protokoll und die Domain gleich sein müssen um Anfragen starten zu dürfen. Das ist zwar sicher, aber leider nicht immer praktisch.

Aber da gibt”™s doch bestimmt einen Trick?

Ja. Es gibt sogar eine ganze Menge verschiedener Möglichkeiten das Problem zu umgehen. Wenn man nach "Cross Domain Ajax” such bekommt man einen bunten Strauß an Lösungen, ich hab bestimmt einen halben Tag gebraucht um mir die verschieden Lösungen anzuschauen. Man könnte einen zum Beispiel einen Proxy einsetzen oder Flash/Silverlight nutzen usw... Für mich war die beste Lösung JSONP zu nutzen.

 

Was ist JSONP?

JSONP steht für "JSON with padding". Die Idee ist so simpel wie Clever, man macht sich eine Sicherheitslücke in der Implementation der Same Origin Policy der Browser zu nutze. Man kann zwar keine Requests zu anderen Domains starten aber man kann dynamisch Javascript Dateien von anderen Domains einbinden. Und in diese packt man einfach seine Daten. Das Ganze hat den Nachteil das man Daten nur per GET übergeben kann und kein POST möglich ist. Wer mehr Daten übertragen möchte kann allerdings auf andere Tricks zurückgreifen oder muss sich etwas einschränken.
jQuery macht die Implementation an dieser Stelle wieder sehr einfach und gibt uns die entsprechenden Methoden an die Hand.

Und so sieht”™s aus

 
Auf dem Client:
      $.ajax({
                dataType: 'jsonp',
                jsonp: 'jsonp_callback',
                url: 'http://localhost:56761/TestService.ashx',
                success: function (j) {
                    alert(j.response);
                },
            });     

Der Unterschied zum "normalen" jQuery Request ist eigentlich nur die Zeile "jsonp: 'jsonp_callback'" diese gibt den GET Parameternamen an in dem jQuery den Namen der Calback Funktion an den Server übermittelt.

Bei jQuery funktioniert das ganze so:

  1. Es wird ein <script> Tag erzeugt das auf die angegebene Adresse verweist, dabei wird als Parameter wird eine Zufallszahl übergeben(das ist dann der Name der Callbackfunktion).
  2. Der Server baut als Antwort eine Javascript-Datei zusammen die eine Funktion mit dem Namen der Zufallszahl aufruft und die Daten im JSON Format übergibt.
  3. Der Browser bindet das Script ein und führt das ganze aus. jQuery übergibt uns jetzt die Daten an das "success" Event.
Und auf dem Server:
string response = context.Request.Params["jsonp_callback"];
       response += "({\"response\":\"" + context.Session["RequestCounter"]  + " requests startet\"});";
context.Response.Write(response);

image

Für dieses Beispiel habe ich einen Generic Handler (.ashx) benutzt. Man könnte sicherlich auch einen WCF benutzen.
Die Beispielanwendung besteht aus zwei Projekten, einen Client das "CrossDomainAjax" Projekt und einen Service dem "SourceDomain" Projekt. Um die Demo zu starten müsst ihr mit:
Rechtsklick auf den Projektnamen -> Debug -> Start New Instance

Beide Projekte starten. Danach solltest du dann ein alert mit einer 1 im Browser sehen. Mit diesen Beispiel habe ich noch ausprobiert ob ich auf dem Server dann auch Zugriff auf die Sessesion habe. Und es geht. Bei jeden neu laden der Seite erhöht sich dann der Wert um eins. Gut, das ist jetzt kein spannendes Beispiel aber ich hoffe ihr verzeiht mit das :)

Den Demo Code gibt”™s hier. Viel Spaß.