REST(Representational State Transfer)作為一種優秀的架構風格,自誕生以來越來越受廣大開發人員的青睞。對沒有接觸過REST的開發人員,可以參閱本人的上一篇部落格:對REST架構的理解及Jquery+JSON+RESTful WCF 。
由於REST推崇的簡易型,以及基於HTTP協議的特點,它又有一些什麼樣的特性呢。?本問將圍繞這個主題分兩部分展開,並結合Demo程式加以介紹。第一部分介紹涉及到的知識點,第二部分介紹Demo。
主要涉及到的知識點如下:
1、綁定協議與行為(webHttpBinding 與webHttpBehavior)
2、Action的定義(POST、GET、DELETE、PUT)
3、URI(Uniform Resource Identifier)的指定
4、webServiceHost與webServiceHostFactory
*1、綁定協議與行為(webHttpBinding 與webHttpBehavior)
眾所周知,WCF中支援的協議有很多,如wsHttpBinding等ws-*系列的、netTcpBinding、支援MSMQ的系列協議等。在構建REST架構風格的WCF中
我們使用的協議為webHttpBinding 。與之相對應的行為則是webHttpBehavior。
MSDN對他們的的描述分別為:
webHttpBinding:一個綁定,可用於為通過 HTTP 要求(而不是 SOAP 訊息)公開的 Windows Communication Foundation (WCF) Web 服務配置終結點。
webHttpBehavior:啟用 Windows Communication Foundation (WCF) 服務的 Web 編程模型。
WebHttpBehavior 行為與 WebHttpBinding 綁定一起使用時,支援 WCF 公開和訪問 Web 樣式服務。WebServiceHost 會自動將此行為添加到使用 WebHttpBinding 的終結點。
webHttpBinding作為REST 架構風格下的WCF 所使用的協議,它和其他協議一樣通知WCF如何為通訊建立通道堆棧,也就是建立相應的Channel以用於
通訊。webHttpBehavior的作用是為REST WCF的端點提供行為的配置,它決定了WebHttpDispatchOperationSelector如何決定選擇何種路由方式
來訪問資源。
*2、Action中的各個動詞決定了對資源進行何種操作。
POST:對用戶端知曉的資源進行添加。它是WebInvokeAttribute預設的操作動作
Get:對資源進行擷取。它是WebGetAttribute預設的操作動作
DELETE:對資源進行刪除。一般由WebInvokeAttribute指定
PUT:對資源進行添加或者修改。一般由WebInvokeAttribute指定
*3、URI
URI(Uniform Resource Identifier)的指定是通過REST WCF編程模型中的WebGetAttribute、 WebInvokeAttribute兩種特性來標識的。它通過將
WebGetAttribute、 WebInvokeAttribute兩種特性的UriTemplate屬性指定。通常將它指定在服務契約對應的介面上,WebHttpDispathOperationSelector通過URI來決定
對資源進行操作。樣本定義如下:
[OperationContract]
[WebGet(UriTemplate = "/")]
List<LogEntity> GetAll();
*4、webServiceHost與webServiceHostFactory
對WCF有些瞭解的人都知道,它的配置是比較複雜的。REST所推崇的是簡易型,因此在REST WCF編程模型中,MS推出了webServiceHost
與webServiceHostFactory來簡化我們的配置。webServiceHost繼承自ServiceHost,使用它,我們將不再需要對webHttpBinding與
webHttpBehavior進行配置,webServiceHost會自動建立端點,並使用webHttpBinding與webHttpBehavior對其進行配置。
MSDN中對webServiceHost的說明如下:
如果 WebServiceHost 在服務說明中找不到終結點,則它將在服務的基址中自動為 HTTP 和 HTTPS 基址建立一個預設終結點。如果使用者已在基址中明確配置
終結點,則它不會自動建立終結點。WebServiceHost 會自動設定終結點的綁定,以便在安全虛擬目錄中使用時與關聯的 Internet 資訊服務 (IIS) 安全設定一起使用。
當建立預設 HTTP 終結點時,WebServiceHost 同時禁用 HTTP 協助頁和 Web 服務描述語言 (WSDL) GET 功能,以使中繼資料終結點不干擾預設 HTTP 終結點。
此外,WebServiceHost 類會將 WebHttpBehavior 添加到所有沒有該行為但具有 WebMessageEncodingElement 的終結點中。如果服務上的所有操作都具有空的 HTTP 要求本文,或者都將 HTTP 要求本文以流的形式處理,則 WebServiceHost 會自動為綁定配置適當的內容類型映射器。
請注意:在3.5中它會禁用REST WCF中的協助(help)頁面。
WebServiceHostFactory ,繼承自ServiceHostFactory,使用它,我們將無需對REST WCF進行配置,只需在svc檔案的指令中指定它即可。樣本如下:
<%@ ServiceHost Service="LogServices.LogServices" Factory="System.ServiceModel.Activation.WebServiceHostFactory"%>
需要說明的是:Service屬性需指明是實現服務契約的類。
第二部分:Demo樣本程式。
開發環境:VS2008 SP1
程式結構如:
Contracts:定義了服務契約。
代碼如下:
[ServiceContract]public interface Ilog{[OperationContract][WebGet(UriTemplate = "/")]List<LogEntity> GetAll();[OperationContract][WebGet(UriTemplate = "Get/{year}/{month}")]List<LogEntity> GetMonthLog(string year,stringmonth);}[DataContract]public class LogEntity{[DataMember]public int ID { get; set; }[DataMember]public string EventName { get; set; }[DataMember]public string Level { get; set; }[DataMember]public DateTime Time { get; set; }}
LogServices:實現服務契約,提供服務
代碼如下:
public List<LogEntity> GetAll(){return GetLogEntityList();}public List<LogEntity> GetMonthLog(string year, string month){List<LogEntity> logEntities = GetLogEntityList();List<LogEntity> logList = new List<LogEntity>();logEntities.ForEach(log =>{if (log.Time.Year.ToString() == year && log.Time.Month.ToString() == month){logList.Add(log);}});return logList;}
順便大家可以看看設定檔,使用WebServiceHostFactory不需要對WCF進行配置。設定檔如下:
<?xml version="1.0"?><configuration><configSections><sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"><sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"><section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/><sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"><section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/><section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/><section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/><section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/></sectionGroup></sectionGroup></sectionGroup></configSections><appSettings/><connectionStrings/><system.web><!-- 設定 compilation debug="true" 可將偵錯符號插入已編譯的頁面中。但由於這會 影響效能,因此只在開發過程中將此值 設定為 true。--><compilation debug="true"><assemblies><add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/><add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/><add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/><add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/></assemblies></compilation><!--通過 <authentication> 節可以配置 ASP.NET 用來 識別進入使用者的安全身分識別驗證模式。 --><authentication mode="Windows"/><!--如果在執行請求的過程中出現未處理的錯誤,則通過 <customErrors> 節可以配置相應的處理步驟。具體說來,開發人員通過該節可以配置要顯示的 html 錯誤頁以代替錯誤堆疊追蹤。<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm"><error statusCode="403" redirect="NoAccess.htm" /><error statusCode="404" redirect="FileNotFound.htm" /></customErrors>--><pages><controls><add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/><add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></controls></pages><httpHandlers><remove verb="*" path="*.asmx"/><add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/><add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/><add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/></httpHandlers><httpModules><add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></httpModules></system.web><system.codedom><compilers><compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"><providerOption name="CompilerVersion" value="v3.5"/><providerOption name="WarnAsError" value="false"/></compiler></compilers></system.codedom><!-- 在 Internet 資訊服務 7.0 下運行 ASP.NET AJAX 需要 system.webServer節。對早期版本的 IIS 來說則不需要此節。--><system.webServer><validation validateIntegratedModeConfiguration="false"/><modules><remove name="ScriptModule"/><add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></modules><handlers><remove name="WebServiceHandlerFactory-Integrated"/><remove name="ScriptHandlerFactory"/><remove name="ScriptHandlerFactoryAppServices"/><remove name="ScriptResource"/><add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/><add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/><add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></handlers></system.webServer><runtime><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/><bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/></dependentAssembly><dependentAssembly><assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/><bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/></dependentAssembly></assemblyBinding></runtime><!--<system.serviceModel></system.serviceModel>--></configuration>
RESTWCFDemo:寄宿服務,並調用服務。由於REST WCF服務的寄宿需要IIS,所以程式的用戶端與服務端直接放在了一個Web工程下面。
直接在IE中調用服務查看運行效果。
1、調用List<LogEntity> GetAll()。結果如:
2、調用GetMonthLog。結果如: