HOW TO:將啟用 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 2010。
在程序之後的範例中,會提供來自本主題中所述程序的程式碼。
如需詳細資訊 透過已啟用 AJAX 端點公開 WCF 服務的詳細資訊,請參閱 HOW TO:使用組態新增 ASP.NET AJAX 端點主題。
若要建立並測試 ASP.NET Web 服務應用程式
開啟 Visual Studio 2010。
在 [檔案] 功能表上,選取 [新增]、[專案]、[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 公開端點。
如需詳細資訊 如何存取這個服務的詳細資訊,請參閱Using Web Services in ASP.NET AJAX。
現在您已準備好要轉換這個服務,以使用 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 作業,並設定 RequestFormat 屬性以傳回 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="https://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].
}
}
DataContractJsonSerializer 不支援 XmlDocument 型別,因為它無法由 XmlSerializer 來序列化。您可以使用 XDocument 型別,或是改為序列化 DocumentElement。
如果 ASMX Web 服務正並存升級及移轉至 WCF 服務,請避免將兩種型別對應至用戶端上相同的名稱。如果在 WebMethodAttribute 和 ServiceContractAttribute 中使用相同的型別,會造成序列化程式中的例外狀況:
如果先新增 WCF 服務,則叫用 ASMX Web 服務上的方法會造成 ConvertValue 中的例外狀況,因為在 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 |
---|---|---|
SerializationException |
null |
|
Value 的序列化 |
{} (or {"__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 值。 |