Vorgehensweise: Migrieren AJAX-aktivierter ASP.NET-Webdienste nach WCF
In diesem Thema werden Verfahren zum Migrieren eines einfachen ASP.NET-AJAX-Diensts zu einem entsprechenden AJAX-fähigen Windows Communication Foundation-Dienst (WCF) beschrieben. Es wird gezeigt, wie eine funktional äquivalente WCF-Version eines ASP.NET-AJAX-Diensts erstellt wird. Die beiden Dienste können parallel eingesetzt werden. Der WCF-Dienst kann auch den ASP.NET-AJAX-Dienst ersetzen.
Die Migration eines vorhandenen ASP.NET-AJAX-Diensts zu einem WCF-AJAX-Dienst bietet Ihnen folgende Vorteile:
Sie können den AJAX-Dienst mit nur minimaler zusätzlicher Konfiguration als SOAP-Dienst verfügbar machen.
Sie können von WCF-Funktionen wie beispielsweise der Ablaufverfolgung und vielen weiteren Vorteilen profitieren.
Bei den folgenden Verfahren wird davon ausgegangen, dass Sie Visual Studio 2012 verwenden.
Der Code, der sich aus den hier besprochenen Verfahren ergibt, wird in dem Beispiel im Anschluss an das Verfahren bereitgestellt.
Weitere Informationen dazu, wie sie einen WCF-Dienst über einen AJAX-fähigen Endpunkt verfügbar machen, finden Sie im Thema Gewusst wie: Verwenden der Konfiguration zum Hinzufügen eines ASP.NET-AJAX-Endpunkts.
So erstellen und testen Sie die ASP.NET-Webdienstanwendung
Öffnen Sie Visual Studio 2012.
Wählen Sie im Menü Datei nacheinander die Optionen Neu, Projekt, Web und ASP.NET-Webdienstanwendung aus.
Nennen Sie das Projekt
ASPHello
, und klicken Sie auf OK.Entfernen Sie in der Datei Service1.asmx.cs die Kommentarzeichen vor der Zeile, die
System.Web.Script.Services.ScriptService]
enthält, damit AJAX für diesen Dienst aktiviert wird.Klicken Sie im Menü Build (Erstellen) auf Build Solution (Projektmappe erstellen).
Wählen Sie im Menü Debuggen die Option Ohne Debuggen starten aus.
Wählen Sie auf der generierten Webseite den Vorgang
HelloWorld
aus.Klicken Sie auf der Testseite für
HelloWorld
auf die Schaltfläche Aufrufen. Sie sollten die folgende XML-Antwort empfangen.<?xml version="1.0" encoding="utf-8" ?> <string xmlns="http://tempuri.org/">Hello World</string>
Diese Antwort bestätigt Ihnen, dass Sie nun über einen funktionierenden ASP.NET AJAX-Dienst verfügen und insbesondere, dass der Dienst jetzt einen Endpunkt unter Service1.asmx/HelloWorld verfügbar gemacht hat, der auf HTTP POST-Anforderungen antwortet und XML zurückgibt.
Jetzt können Sie diesen Dienst für die Verwendung eines WCF-AJAX-Diensts konvertieren.
So erstellen Sie eine äquivalente WCF AJAX-Dienstanwendung
Klicken Sie mit der rechten Maustaste auf das Projekt ASPHello, und wählen Sie nacheinander Hinzufügen, Neues Element und AJAX-aktivierter WCF-Dienst aus.
Nennen Sie den Dienst
WCFHello
, und klicken Sie auf Hinzufügen.Öffnen Sie die Datei WCFHello.svc.cs.
Kopieren Sie aus „Service1.asmx.cs“ die folgende Implementierung des Vorgangs
HelloWorld
.public string HelloWorld() { return "Hello World"; }
Ersetzen Sie in der Datei „WCFHello.svc.cs“ den folgenden Code durch die kopierte Implementierung des
HelloWorld
-Vorgangs.public void DoWork() { // Add your operation implementation here return; }
Geben Sie das Attribut
Namespace
für ServiceContractAttribute alsWCFHello
an.[ServiceContract(Namespace="WCFHello")] [AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Required)] public class WCFHello { … }
Fügen Sie das WebInvokeAttribute zum Vorgang
HelloWorld
hinzu, und legen Sie die Eigenschaft ResponseFormat so fest, dass Xml zurückgegeben wird. Beachten Sie, dass der Standardrückgabetyp Json ist, sofern nichts anderes festgelegt wird.[OperationContract] [WebInvoke(ResponseFormat=WebMessageFormat.Xml)] public string HelloWorld() { return "Hello World"; }
Klicken Sie im Menü Build (Erstellen) auf Build Solution (Projektmappe erstellen).
Öffnen Sie die Datei „WCFHello.svc“, und wählen Sie im Menü Debuggen die Option Ohne Debuggen starten aus.
Der Dienst macht jetzt einen Endpunkt bei
WCFHello.svc/HelloWorld
verfügbar, der auf HTTP POST-Anforderungen antwortet. HTTP POST-Anforderungen können im Browser nicht getestet werden, aber der Endpunkt gibt die folgenden XML-Daten zurück.<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Hello World</string>
Die Endpunkte
WCFHello.svc/HelloWorld
undService1.aspx/HelloWorld
sind jetzt funktionsäquivalent.
Beispiel
Der Code, der sich aus den hier besprochenen Verfahren ergibt, wird im folgenden Beispiel bereitgestellt.
//This is the ASP.NET code in the Service1.asmx.cs file.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using System.Web.Script.Services;
namespace ASPHello
{
/// <summary>
/// Summary description for Service1.
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
// 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 Service1 : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
}
}
//This is the WCF code in the WCFHello.svc.cs file.
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
namespace ASPHello
{
[ServiceContract(Namespace = "WCFHello")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class WCFHello
{
// Add [WebInvoke] attribute to use HTTP GET.
[OperationContract]
[WebInvoke(ResponseFormat=WebMessageFormat.Xml)]
public string HelloWorld()
{
return "Hello World";
}
// Add more operations here and mark them with [OperationContract].
}
}
Der XmlDocument-Typ wird vom DataContractJsonSerializer nicht unterstützt, da er vom XmlSerializer nicht serialisiert werden kann. Sie können entweder einen XDocument-Typ verwenden oder stattdessen das DocumentElement serialisieren.
Wenn ASMX-Webdienste parallel mit WCF-Diensten aktualisiert und migriert werden, sollten Sie vermeiden, dass zwei Typen auf dem Client demselben Namen zugeordnet werden. Denn andernfalls wird beim Serialisieren eine Ausnahme ausgelöst, wenn der gleiche Typ in einem WebMethodAttribute und einem ServiceContractAttribute verwendet wird.
Wird der WCF-Webdienst zuerst hinzugefügt, löst ein Aufruf der Methode im ASMX-Webdienst eine Ausnahme in ConvertValue(Object, Type, String) aus, da die WCF-Formatdefinition der Reihenfolge im Proxy Vorrang hat.
Wird der ASMX-Webdienst zuerst hinzugefügt, löst der Aufruf der Methode im WCF-Dienst eine Ausnahme in DataContractJsonSerializer aus, da die Webdienst-Formatdefinition der Reihenfolge im Proxy Vorrang hat.
Es gibt bedeutende Unterschiede im Verhalten von DataContractJsonSerializer und dem ASP.NET AJAX JavaScriptSerializer. Beispielsweise stellt der DataContractJsonSerializer ein Wörterbuch als Array von Schlüssel-Wert-Paaren dar, wohingegen der ASP.NET AJAX JavaScriptSerializer ein Wörterbuch als tatsächliche JSON-Objekte darstellt. Deshalb ist das Folgende die Darstellung eines Wörterbuchs in ASP.NET AJAX.
Dictionary<string, int> d = new Dictionary<string, int>();
d.Add("one", 1);
d.Add("two", 2);
Dieses Wörterbuch wird entsprechend der folgenden Liste in JSON-Objekten dargestellt:
[{"Key":"one","Value":1},{"Key":"two","Value":2}] vom DataContractJsonSerializer
{"one":1,"two":2} vom ASP.NET AJAX JavaScriptSerializer
Der DataContractJsonSerializer ist insofern leistungsfähiger, als dass er Wörterbücher handhaben kann, bei denen der Schlüsseltyp keine Zeichenfolge ist. Der JavaScriptSerializer kann dies nicht. Letzterer ist jedoch JSON-freundlicher.
Die wichtigsten Unterschiede zwischen diesen Serialisierern werden in der folgenden Tabelle zusammengefasst.
Unterschiedskategorie | DataContractJsonSerializer | ASP.NET AJAX JavaScriptSerializer |
---|---|---|
Deserialisieren des leeren Puffers (new byte[0]) in Object (oder Uri oder andere Klassen). | SerializationException | NULL |
Serialisierung von Value | {} (oder {"__type":"#System"}) | Null |
Serialisierung der privaten Member von [Serializable]-Typen. | serialisiert | nicht serialisiert |
Serialisierung der öffentlichen Eigenschaften von ISerializable-Typen | nicht serialisiert | serialisiert |
"Erweiterungen" von JSON | Entspricht der JSON-Spezifikation, die erfordert, dass Objektmembernamen in Anführungszeichen gesetzt werden müssen ({"a":"hello"}). | Lässt Namen von Objektmembern ohne Anführungszeichen zu ({a:"hello"}). |
DateTime UTC (Coordinated Universal Time) | Unterstützt die Formate „\/Date(123456789U)\/“ oder „\/Date\(\d+(U|(\+\-[\d{4}]))?\)\\/)“ nicht. | Unterstützt die Formate „\/Date(123456789U)\/“ und „\/Date\(\d+(U|(\+\-[\d{4}]))?\)\\/)“ als DateTime-Werte. |
Darstellung von Wörterbüchern | Ein Array aus KeyValuePair<K,V>, behandelt Schlüsseltypen, die keine Zeichenfolgen sind. | Als tatsächliche JSON-Objekte, behandelt aber nur Schlüsseltypen, die Zeichenfolgen sind. |
Escapezeichen | Immer mit einem Schrägstrich (/) als Escapezeichen; lässt nie ungültige JSON-Zeichen ohne Escapezeichen wie "\n" zu. | Mit einem Schrägstrich (/) als Escapezeichen für DateTime-Werte. |