WCF服務能夠輸出JSON,通過HTTP進行傳輸(不一定要用SOAP進行資料封裝)。我們要做的是,使端點使用webHttpBinding綁定模型,並通過新的特性來啟用Web指令碼調用。
構建一個簡單的WCF服務
在VS2008中建立一個新Web網站,添加一個新的WCF服務,並將該項命名為TimeService。
以WCF服務的形式重寫TimeService
添加新項後,我們會發現項目中多了一個服務端點(timeservice.svc),與其相關的代碼檔案(如wcftimeservice.cs)位於App_Code檔案家下。此外,web.config檔案也會被修改,用於向系統註冊剛剛建立的服務。
開發人員通常應該通過介面來定義服務的協定,雖然並不嚴格要求這麼做,但我們能夠通過此方法在同一個類中實現多個協定:
namespace Core35.Services.Wcf
{
//Contract
[ServiceContract(Namespace="Core35.Services", Name="WcfTimeService")]
public interface ITimeService
{
[OperationContract]
DateTime GetTime();
[OperationContract]
string GetTimeFormat(string format);
}
}
ITimeService介面代表的有服務的協定。ServiceContract特性用於標記協定,OperationContract特性用於標記方法。對於更簡單的情況,我們可以用類定義協定(直接使用ServiceContract和OperationContract),並直接實現。
注意此處ServiceContract特性的Namespace和Name屬性值,這兩者對支援AJAX的WCF服務有著非常重要的意義。下面是一個實現ITimeService協定的類:
using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
namespace Core35.Services.Wcf
{
[AspNetCompatibilityRequirements(
RequirementsMode=AspNetCompatilityRequirementMode.Allowed)]
public class TimeService : ITimeService
{
public DateTime GetTime()
{
return DateTime.Now;
}
public class GetTimeFormat(string format)
{
return DateTime.Now.ToString(format);
}
}
}
TimeService暴露了兩個公用端點,分別為GetTime和GetTimeFormat.
WCF服務的註冊
用於調用該介面方法的端點定義在SVC檔案中,如timeservice.svc檔案:
<%@ ServiceHost Debug="true" Service="Core35.Services.Wcf.TimeService"
CodeBehind="~/App_Code/WcfTimeService.cs" %>
ServiceHost指令用於指示源檔案的名稱和實現該方法的類型。如果服務相關的代碼以內聯方式置於SVC檔案中,則必須另外指定Language屬性。
最後要完成的步驟是在宿主ASP.NET應用程式的web.config檔案中註冊該服務的使用方式:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="TimeServiceAspNetAjaxBehavior">
<enableWebScript>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service name="Core35.Services.Wcf.TimeService">
<endpoing address=""
behaviorConfiguration="TimeServiceAspNetAjaxBehavior"
binding="webHttpBinding"
contract="Core35.Services.Wcf.ITimeService" />
</service>
</services>
</system.serviceModel>
首先,註冊這些端點的一系列行為。為此,聲明它能夠接受通過指令碼發起的Web請求。enableWebScript元素在邏輯上等價於修改Web服務類時使用的ScriptService特性。
隨後,我們要列出寄放在當前ASP.NET應用程式中的服務。
服務測試
我們如何在用戶端ASP.NET頁面中使用它呢?對於開發人員來說,這無異於調用Web服務。
首先,我們向指令碼管理器註冊該服務的SVC端點:
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="~/TimeService.svc" />
</Services>
</asp:ScriptManager>
處理該指令碼時,ScriptManager控制項會觸發額外的請求,為指定的WCF服務產生和下載JavaScript代理類。
該代理類的名稱取決於協定中ServiceContract特性的Namespace和Name屬性。如果不設定這兩個屬性,保留其預設值,那麼這個JavaScript代理類的名稱為Tempuri.org.ITimeService,其中Tempuri.org是預設的命名空間,介面的名稱即為協定的預設名稱。
服務類的名稱與JavaScript代理類的名稱間沒有關係。
使用JavaScript調用WCF服務的方法:
<script language="javascript" type="text/javascript">
function getTime()
{
Core35.Services.WcfTimeService.GetTimeFormat("dd-MM-yyyy [hh:mm:ss]", onMethodCompleted);
}
function onMethodComplete(results)
{
$get("lblCurrentTime").innerText = results;
}
</script>
與ASP.NET AJAX Web服務類似,每個JavaScript代理方法也支援一且額外的參數--用於處理操作成功或失敗的回呼函數。
ASP.NET相容模式
當建立ASP.NET AJAX Web時,服務類預設會由AspNetCompatibilityRequirements特性修飾。
雖然WCF服務的訊息與傳輸協議無關,但如果它們處於ASP.NET AJAX應用程式的上下文中,其工作方式與ASMX服務非常接近。通過AspNetCompatibilityRequirements屬性,我們可使WCF和ASMX服務按同一種模型工作。與ASMX服務相容使WCF服務能夠訪問HttpContext對象,進而可以訪問其他ASP.NET內部對象。這種相容性需要在兩個層面設定,第一個層面位於web.config檔案中,設定其serviceHostingEnvironment節點;第二個層面,開發人員需通過AspNetCompatibilityRequirements特性顯式地為WCF服務選擇相容模式。