作法:將啟用 AJAX 的 ASP.NET Web 服務移轉至 WCF
本主題將概述用來將基本 ASP.NET AJAX 服務移轉至相等啟用 AJAX 的 Windows Communication Foundation (WCF) 服務的程序。 其中將示範如何建立功能相等 WCF 版本的 ASP.NET AJAX 服務。 然後這兩項服務可以並存使用,或是 WCF 服務可以用於取代 ASP.NET AJAX 服務。
將現有的 ASP.NET AJAX 服務移轉至 WCF AJAX 服務可為您提供下列優點:
您可以使用最少的額外組態,將您的 AJAX 服務公開為 SOAP 服務。
您可以從 WCF 功能獲益,例如追蹤等等。
下列程序假設使用的是 Visual Studio 2012。
在程序之後的範例中,會提供來自本主題中所述程序的程式碼。
透過啟用 AJAX 的端點公開 WCF 服務的詳細資訊,請參閱如何:使用設定新增 ASP.NET AJAX 端點主題。
若要建立並測試 ASP.NET Web 服務應用程式
開啟 Visual Studio 2012。
在 [檔案] 功能表上,選取 [新增]、[專案]、[Web],然後選取 [ASP.NET Web Service 應用程式]。
命名專案
ASPHello
,然後按一下 [確定]。在 Service1.asmx.cs 檔案中,取消包含
System.Web.Script.Services.ScriptService]
的字行註解以便為此服務啟用 AJAX。從 [組建] 功能表上,選取 [組建解決方案]。
從 [偵錯] 功能表中,選取 [啟動但不偵錯]。
在產生的網頁中,選取
HelloWorld
作業。在 測試頁上按一下 [叫用]
HelloWorld
按鈕。 您應該會收到下列 XML 回應。<?xml version="1.0" encoding="utf-8" ?> <string xmlns="http://tempuri.org/">Hello World</string>
這個回應會確認您現在有正在運作的 ASP.NET AJAX 服務,而且特別的是,服務現在已在回應 HTTP POST 要求並傳回 XML 的 Service1.asmx/HelloWorld 公開端點。
現在您已準備好要轉換這個服務,以使用 WCF AJAX 服務了。
建立相等的 WCF AJAX 服務應用程式
以滑鼠右鍵按一下 [ASPHello] 專案並選取 [新增]、[新增項目],然後選取 [已啟用 AJAX 的 WCF 服務]。
將服務命名為
WCFHello
,然後按一下 [新增]。開啟 WCFHello.svc.cs 檔案。
請從 Service1.asmx.cs 複製
HelloWorld
作業的下列實作。public string HelloWorld() { return "Hello World"; }
將複製的
HelloWorld
作業實作貼上至 WCFHello.svc.cs 檔案,以取代下列程式碼。public void DoWork() { // Add your operation implementation here return; }
指定ServiceContractAttribute 的
Namespace
屬性名稱為WCFHello
。[ServiceContract(Namespace="WCFHello")] [AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Required)] public class WCFHello { … }
將 WebInvokeAttribute 新增至
HelloWorld
作業,並設定 ResponseFormat 屬性以傳回 Xml。 請注意,如果沒有設定,預設傳回型別為 Json。[OperationContract] [WebInvoke(ResponseFormat=WebMessageFormat.Xml)] public string HelloWorld() { return "Hello World"; }
從 [組建] 功能表上,選取 [組建解決方案]。
開啟 WCFHello.svc 檔案,然後從 [偵錯] 功能表中,選取 [啟動但不偵錯]。
服務現在會在回應 HTTP POST 要求的
WCFHello.svc/HelloWorld
公開端點。 HTTP POST 要求無法從瀏覽器來測試,但是端點會傳回下列 XML。<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Hello World</string>
WCFHello.svc/HelloWorld
和Service1.aspx/HelloWorld
端點現在的功能相等。
範例
下列範例中會提供來自本主題中所述程序的程式碼。
//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].
}
}
XmlDocument 不支援 DataContractJsonSerializer 型別,因為它無法由 XmlSerializer 來序列化。 您可以使用 XDocument 型別,或是改為序列化 DocumentElement。
如果 ASMX Web 服務正並存升級及移轉至 WCF 服務,請避免將兩種型別對應至用戶端上相同的名稱。 如果在 WebMethodAttribute 和 ServiceContractAttribute 中使用相同的型別,會造成序列化程式中的例外狀況:
如果先新增 WCF 服務,則叫用 ASMX Web 服務上的方法會造成 ConvertValue(Object, Type, String) 中的例外狀況,因為在 Proxy 中順序的 WCF 樣式定義會取得優先權。
如果先新增 ASMX Web 服務,則叫用 WCF 服務上的方法會造成 DataContractJsonSerializer 中的例外狀況,因為在 Proxy 中順序的 Web 服務樣式定義會取得優先權。
DataContractJsonSerializer 和 ASP.NET AJAX JavaScriptSerializer 之間在行為上有許多不同之處。 例如,DataContractJsonSerializer 會將字典表示為索引鍵/值配對的陣列,而 ASP.NET AJAX JavaScriptSerializer 會將字典表示為實際的 JSON 物件。 因此下面是在 ASP.NET AJAX 中表示的字典。
Dictionary<string, int> d = new Dictionary<string, int>();
d.Add("one", 1);
d.Add("two", 2);
這個字典在 JSON 物件中的表示如下列清單所示:
[{"Key":"one","Value":1},{"Key":"two","Value":2}],透過 DataContractJsonSerializer
{"one":1,"two":2} 透過 ASP.NET AJAX JavaScriptSerializer
DataContractJsonSerializer 的功能較為強大,因為它可以處理其中金鑰類型不是字串的字典,但是 JavaScriptSerializer 卻無法這麼做。 然而後者較容易用來處理 JSON。
下表將摘要說明序列化程式之間的許多差異。
差異分類 | DataContractJsonSerializer | ASP.NET AJAX JavaScriptSerializer |
---|---|---|
將空的緩衝區 (新的 byte[0]) 還原序列化成 Object (或 Uri 或一些其他的類別)。 | SerializationException | null |
Value 的序列化 | {} (或 {"__type":"#System"}) | Null |
[Serializable] 型別的私用成員序列化 | 已序列化 | 未序列化 |
ISerializable 型別的公用屬性序列化。 | 未序列化 | 已序列化 |
JSON 的 "Extensions" | 遵守 JSON 規格,需要在物件成員名稱上加上引號 ({"a":"hello"})。 | 支援不加引號的物件成員名稱 ({a:"hello"})。 |
DateTime 以 Coordinated Universal Time (UTC) 時間計算 | 不支援格式「\/Date(123456789U)\/」或「\/Date\(\d+(U|(\+\-[\d{4}]))?\)\\/)」。 | 支援格式「\/Date(123456789U)\/」和「\/Date\(\d+(U|(\+\-[\d{4}]))?\)\\/)」做為 DateTime 值。 |
字典表示法 | KeyValuePair<K,V> 陣列,可處理非字串的金鑰型別。 | 做為實際的 JSON 物件 - 但只能處理屬於字串的金鑰型別。 |
逸出字元 | 一律使用逸出正斜線 (/);絕不允許使用未逸出的無效 JSON 字元,例如 "\n"。 | 使用逸出斜線 (/) 做為 DateTime 值。 |