HowTo: JSON / AJAX – Webservices mit WCF erstellen

Das Thema ist eigentlich schon alt – wie kann man .NET Methoden aus Javascript aufrufen. Mit ASMX Webservices ging dies recht einfach – siehe HowTo – doch geht das auch mit WCF?

Seit .NET 3.5 und Visual Studio 2008 strahlte mich dieses Itemtemplate an:

image

“AJAX-enabled WCF Service” klingt schonmal gut.

Daraus wird dann sowas (ich hab die Standardmethode mal abgewandelt) :

using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;

[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service
{
   // Add [WebGet] attribute to use HTTP GET
   [OperationContract]
   public DateTime GetDateTime()
   {
        return DateTime.Now;
   }

   // Add more operations here and mark them with [OperationContract]
}

Wie üblich, muss man den ScriptManager diesen Service (mit der .svc Endung) noch registrieren:

    <asp:ScriptManager ID="ScriptManager1" runat="server">
        <Services>
            <asp:ServiceReference Path="~/Service.svc" />
        </Services>
    </asp:ScriptManager>

Wenn man dies jetzt einfach mal so ausführt, bekommt man folgendes (im Firebug) zu sehen:

image

Schauen wir uns das Ergebnis jetzt mal per Javascript an:

image

Eigentlich ist es genau dasselbe wie bei den “alten” ASMX Webservices – nur diesmal mit WCF.

Doch im Detail gibt es Unterschiede

Um dies deutlich zu machen, folgender Aufbau der Website:

image

Ich habe einmal einen WCF und einen ASMX Webservice erstellt, mit folgenden Methoden:

- GetDateTime: Gibt ein DateTime Objekt zurück
- GetComplexOne: Gibt einen eigenen Objekttyp “Complex” zurück
- GetComplexList: Gibt eine Collection an “Complex” Typen zurück.

Beschreibung von eigenen Objekttyp “Complex”

image

“GetList” und “GetOne” sind beide statisch. “Number” ist vom Typ integer und die anderen beiden sind Strings.

Erstellung des ASMX Webservice

Der ASMX Webservice ist nicht weiter schwierig:

using System;
using System.Collections;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using System.Collections.Generic;

/// <summary>
/// Summary description for WebService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
[System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService {

    public WebService () {

    }

    [WebMethod]
    public DateTime GetDateTime()
    {
        return DateTime.Now;
    }

    [WebMethod]
    public ComplexType GetComplexOne()
    {
        return ComplexType.GetOne();
    }

    [WebMethod]
    public List<ComplexType> GetComplexList()
    {
        return ComplexType.GetList();
    }
}  

Wichtige Attribute sind hier das für die Ajax-Integration wichtige “ScriptServiceAttribut“, sowie das “WebMethodAttribut“. Wer mehr Infos möchte, dem sei dieser MSDN Artikel ans Herz gelegt.

Im Javascript werden diese Webmethoden in solch einen Wrapper gesetzt:

image

Erstellung des WCF Services

Der WCF Service ist ähnlich vom Aufbau, allerdings sind andere Attribute und Klassen im Gebrauch:

using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.ServiceModel.Description;
using System.Collections.Generic;

[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service
{
   // Add [WebGet] attribute to use HTTP GET
   [OperationContract]
   public DateTime GetDateTime()
   {
        return DateTime.Now;
   }

    [OperationContract]
    public ComplexType GetComplexOne()
    {
        return ComplexType.GetOne();
    }

    [OperationContract]
    public List<ComplexType> GetComplexList()
    {
        return ComplexType.GetList();
    }
   // Add more operations here and mark them with [OperationContract]
}

Das wichtigste Attribut für den JSON Webserive ist das “AspNetCompatibilityRequirementsAttribute” und dann für WCF typisch das “OperationContractAttribute“.

Wenn man das nun so kompiliert und die beiden Services in den ScriptManager einbindet, bekommen wir einen Fehler in unserem WCF Service!

Den “ComplexType” für WCF zugänglich machen

WCF serializiert nur das, was konfiguriert wurde (um es mal einfach auszudrücken). Dafür müssen über dem Typen ein “DataContractAttribute” gesetzt werden und über jeden Member ein “DataMemberAttribute“.

Sobald dies gemacht wurde, sieht man im Javascript folgendes:

image

Die serializierten Objekte sind identisch mit der ASMX Variante.

Mehr zum Thema JSON Serializierung: Stand-Alone JSON Serialization.

Zwischenfazit

Läuft schonmal ganz gut und bis auf die Sache mit dem “DataContract/MemberAttributen” sind kaum Unterschiede. Wenn man etwas mehr ins Detail geht, findet man allerdings noch das ein oder andere, was anders ist:

Unterschiede Namespaces:

Wenn man um die ASMX “WebService” Klasse ein Namespace “WebServiceNamespace” zieht, wird aus dem Javascript Wrapper folgendes:

image

Wenn man um den WCF Service einen Namespace zieht, passiert erstmal garnix – warum weiß ich spontan auch leider nicht. Um jedoch den selben Effekt zu erzielen wie bei der ASMX Variante muss man im “ServiceContractAttribute” einen Namespace setzen:

[ServiceContract(Namespace = "ServiceNamespace")]

image

Unterschiede HttpContext / ASP.NET Integration:

In einem WCF Service kann man nicht auf HttpContext zugreifen, sondern auf einen OperationContext. Dies und mehr ist auf der MSDN ganz gut beschrieben:

WCF Services and ASP.NET

Weitere Infos & Fazit:

Auf der MSDN ist noch ein weiteres einfaches Beispiel zu finden.
Hier sind auch noch zwei andere Blogposts zu dem Thema:

WCF Serivces sind eine mächtige Alternative zu den ASMX Webservices und die Integration in eine AJAX Anwendung ist kaum schwieriger als die ASMX Variante – wenn man die Möglichkeit hat und etwas rumexperimentieren möchte, der sollte dies wahrnehmen. Hier noch der Democode:

[ Download Democode ]


Kick It auf dotnet-kicks.de
Wenn dir der Blogpost gefallen hat, dann hinterlasse doch einen Kommentar. Wenn du auf dem Laufenden bleiben willst, abonniere unseren RSS Feed oder folge uns auf Twitter.

About the author

Written by Robert Mühsig

Robert Mühsig (@robert0muehsig) ist Webentwickler und beschäftigt sich mit Web-Frameworks (vor allem dem ASP.NET MVC Framework) und scheut sich auch nicht vor Javascript. Ansonsten bloggt er über all jene Probleme, die ihm über den Weg laufen. Seit 2008 ist er Microsoft MVP für ASP.NET und er arbeitet bei der T-Systems Multimedia Solutions GmbH in Dresden. Treffen kann man ihn online via Twitter (@robert0muehsig) oder dieser Seite oder bei der .NET User Group Dresden.

5 Responses

  1. Danke schön!!!!!

    Reply
  2. Super beschrieben, auch von mir vielen Dank! (mit nur einem Ausrufezeichen :-)

    Reply
  3. Hi !

    Theoretisch sieht das ja ganz gut aus. Es gibt aber – speziell für den Ajax-Gebrauch – nach meiner Erfahrung ein k.o.-Kriterium:WCF bearbeitet alle Requests sequentiell und fällt damit für mich leider völlig aus :-(

    Ich habe eine länger dauerende Operation, die ich zuerst auslöse, dann folgt unmittelbar der Aufruf einer schnell abzuarbeitenden Aufgabe. Beide terminieren “gleichzeitig”. Schaltet man das Asp(x) Sessionmanagement ab [ich brauchs!!] – kommt die kurze Methode auch zuerst zurück.

    Ich habe den WCF Dienst mit der zusätzlichen Implementierung von “IReadOnlySessionState” compiliert, hat aber nichts geändert. Außerdem habe ich noch “ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple, InstanceContextMode=InstanceContextMode.PerCall)”

    mfg–mabra

    Reply
  4. Dass Klapt ja Supper.
    Besten Dank!

    Reply
  5. Ist es möglich ein einen Script Manager zwei Script Refezenzen zu erstellen. Die Erste ist der Alte Webdienst, der Zweite ist der WCF Service, doch der WWCF Service wird leider nicht erkant wen ich einen Versuch per Javascript zugriff Starte.

    Reply

Comment on this post

Letzte Posts

  • image.png
    RavenHQ–RavenDB in der Cloud

    Ayende Rahien hat es heute verkündet – RavenHQ, der RavenDB Cloud Hoster (natürlich von und mit Ayende) ist ab heute raus aus der Beta und man kann es von überall aus nutzen. In der Betaphase waren nur Nutzer von AppHarbor zugelassen. Was ist RavenHQ? RavenHQ ist im Grunde ein gehostes RavenDB in den Rechenzentren von ...

  • image.png
    GitHub for Windows–erste Eindrücke

    Git ist schon eine tolle Sachen und eröffnet viele neue Möglichkeiten – allerdings ist der Einstieg recht hart und selbst wenn man die guten Hilfsanleitungen auf GitHub befolgt, kommt man am Anfang nur langsam vorwärt. Insbesondere ist das Tooling für Windows / .NET Entwickler auch nicht gerade “bekanntes Terrain”. GitHub to the rescue! Die GitHub ...

  • image.png
    Chocolatey–apt-get für Windows

    Durch Zufall bin ich auf das Tool “Chocolatey” gestoßen. Wer die Website sich anschaut, wird evtl. eine Verwandschaft mit NuGet ausmachen. Was macht Chocolatey? Chocolatey ist ein “Maschine Package Manager”, das bedeutet, dass man für seine Maschine einfach Tools runterladen und Updaten kann – direkt über die Konsole. Was ist der Unterschied zu NuGet? NuGet ...

  • image.png
    SASS, LESS & Coffeescript in Visual Studio mit der Web Workbench

    CSS und Javascript sind die “kleinste” Schnittmenge von allen Browsern für die Erstellung von Web-Applikationen. Leider geht dabei etwas komfort verloren, daher lieben alle Webentwickler jQuery! SASS und LESS sind zwei Varianten, wie man “schöner” CSS schreiben kann und Coffeescript versucht Javascript Entwicklung zu vereinfachen. Aber immer der Reihe nach… Was ist SASS? SASS steht ...

  • image.png
    Code-Inside Sample nun auf GitHub: Google Code zu GitHub Migration

    Seit einiger Zeit habe ich Beispielcode auf Google Code bereitgestellt. Einfach nur noch weg von Google Code O-Ton damals war: Ich hatte mich für Google Code entschieden, weil ich hoffe dass früher oder später die Google Code Suche nutzbar ist und es dadurch wenigstens ein kleiner Mehrwert entsteht. Allerdings wirft es momentan noch ein Fehler. ...

Auf Amazon einkaufen & unterstützen

Facebook