本月,我將繼續探討軟件工廠,此次介紹的內容是 Windows® Communication Foundation 的 Web 服務軟件工廠。接著,我將介紹如何自定義指導包,該指導包將提供 一套與 Visual Studio® 2005 集成且自動化常見開發任務的代碼方案。
有兩種服務工廠指導 包可供使用:一種是生成 ASP.NET Web 服務 (ASMX) 代碼的指導包,另一種是生成 Windows Communication Foundation 代碼的指導包。ASMX 版本已隨 MSDN® 提供,而 Windows Communication Foundation 版本直到本文完成之時仍處於開發階段。不過,Windows Communication Foundation 指導包的社區小版本目前能夠在 GotDotNet 上找到(請參閱 practices.gotdotnet.com/svcfactory)。
上次,我們討論了 ASMX 指導包,但是沒有時間對 Windows Communication Foundation 版本進行探討。那麼,今天就讓我們談談這方面的內容。請注意, Windows Communication Foundation 指導包的詳細信息可能在最終發布時會有所變更。
服務工廠 開發過程
首先,我想簡單介紹一下服務工廠的開發過程。p&p 團隊采用的是靈活透明的開發 方法。他們向在線社區發布常規小版本,並詢問社區用戶的反饋意見。但最重要的是他們是如何實際應用 社區的反饋意見來改進產品的下一版本。我曾看過有關開發人員社區對 p&p 產品的影響力方面的第 一手資料。此做法意義深遠,它不僅為想要參與其中的開發人員提供了參與的途徑,並且提高了產品的質 量,各方均能從中獲益。
開發過程中另一有趣的地方是他們如何使用引用實現來促進工作。如圖 1 所示,開發實際的引用實現不僅能夠驗證所推薦實踐的適用性,而且能夠幫助發現可能遺漏掉的新實踐 。最終的推薦實踐集將影響服務工廠的所有隨附內容,包括編寫模式、“如何”主題,當然, 還有指導包。
圖 1 軟件工廠開發過程
入門
一旦下載並安裝了 Windows Communication Foundation 指導包,它就會出現在 Visual Studio 2005“新建項目”對話框中。選擇 Windows Communication Foundation 服務模板,輸入新解決方案的名稱,然後便可開始使用 Windows Communication Foundation 指導包。然後按“確定”啟動可生成初始解決方案結構的方案。 您會發現初始解決方案結構與 ASMX 指導包所使用的非常相似。
最大的區別在於服務層。服務層 包含四個項目:DataContracts、FaultContracts、ServiceContracts 和 ServiceImplementation。這提 供了用於組織要構建的相應 Windows Communication Foundation 產物的邏輯結構。主要更改在於錯誤約 定的項目,這是 Windows Communication Foundation 新引進的概念。另一項更改是,現在服務主機被置 於 Tests 文件夾中。
請記住,如果此初始解決方案結構不能滿足您的確切需求而需要進行更改, 您可以通過解鎖和重組結構來執行更改。一旦將結構按照自己的需求進行組織後,便可重新分配項目職責 ,這實質上是告知服務工廠每個項目應有哪些方案可用。我已經在上一期專欄中對此進行過詳細介紹。
現在,讓我們深入了解一下服務層內部的一些更改。實現 Windows Communication Foundation 服務層可分為幾個步驟。首先,定義要在消息中使用的數據約定。然後,設計組成操作的消息、錯誤和服 務約定。最後,實現服務約定並提供服務端點。
Windows Communication Foundation 指導包提供 許多用於完成這些任務的方案。在 Visual Studio 中,打開“指導導航器”窗口(視圖 | 其 他窗口),您便會看到 Windows Communication Foundation 指導包中提供了各種特定於 Windows Communication Foundation 的方案(請參見圖 2)。
圖 2 指導導航器
數據約定
Windows Communication Foundation 指導包提供了幾種生成數據約定的方法。 如果已經擁有 XML 架構定義,則可以從 XML 架構定義 (XSD) 本身生成數據約定類型。此方案與 ASMX 方案類似,稱為“從架構創建 XML 序列化類型”,它僅在可能的情況下生成 [DataContract] 類型。Windows Communication Foundation 中的 DataContractSerializer 僅支持 XML 架構語言的子集 ,因此,如果架構使用該子集外的內容(如 XML 屬性),方案將轉為生成 XmlSerializer 兼容類型。
從頭開始設計新的數據約定時,您可以運行“創建數據約定”方案,這將啟動一個向導。 該向導會要求您指定類的名稱以及數據約定的名稱(XML 名稱)和命名空間。然後指定數據約定的成員; 請注意,您可以指定 [DataContract] 的各種詳細信息,如 Order 和 IsRequired(請參見圖 3)。按下 “完成”後,將生成如圖 4 所示的類。
Figure 4 WinePreference 類
[DataContractAttribute( Namespace = "http://CohoWinery.DataContracts/2006/09", Name = "WinePreference")] public class WinePreference { private string country; private string region; private string type; [DataMemberAttribute(Name = "Country", Order = 1)] public string Country { get { return this.country; } set { this.country = value; } } ... // 仍然略去屬性 }
圖 3創建數據約定方案
您還可以通過將 Decorate 類型用作 DataContract 方案,將現有的類定義轉 變為數據約定。該方案可在現有類上對各種 [DataContract] 屬性應用過程進行自動化。另外還存在一種 名為“驗證 DataContract”的方案,該方案可分析所選的類,以查看此類能否通過 DataContractSerializer 實現序列化。
消息約定
在開始定義服務約定之前,您還需要定 義將要在各操作中使用的消息約定。ASMX 指導包將此項任務稱為創建消息類型。在 ASMX 中,消息類型 就是 XmlSerializer 類型,代表整個請求或響應消息。如果您將此類型與 ASMX 展開參數樣式一同使用 ,類型本身將定義 SOAP 主體所使用的 XML 的整個結構。
在 Windows Communication Foundation 中,消息類型屬於一流成員。您可以使用一組不同屬性([MessageContract]、 [MessageHeader] 和 [MessageBodyHeader])對其進行定義。消息約定允許您設計整個 SOAP 封裝的結構 。您可以指定哪些字段屬於 SOAP 標頭,哪些字段屬於 SOAP 主體。消息約定還允許您指定消息是否需要 展開(類似於 ASMX 參數樣式)。否則,Windows Communication Foundation 將所有消息封裝在表示操 作名稱的元素內。
Windows Communication Foundation 允許您使用數據約定或消息約定類型來定 義操作。因此,就出現了一個問題:應在何時使用數據約定,何時使用消息約定?p&p 的一般性意見 是,在處理可重用類型(也就是,需要用於五種不同消息中的類型)時應該使用數據約定。而在定義表示 不能重復使用的請求/響應消息的類型時,應使用消息約定。使用消息約定也能提供自定義標頭處理過程 的靈活性,這在設計期間可能成為決定性因素。
如果想要根據數據約定定義消息類型,您只需繼 續使用數據約定方案即可。如果想要定義 Windows Communication Foundation 消息約定,則可使用專門 為其准備的方案。消息約定方案將指導您完成設計現有數據約定之外消息約定的過程,並生成帶有 [MessageContract] 屬性的類定義。
錯誤約定
如果計劃將自定義 SOAP 錯誤返回到客戶端 ,需要在錯誤元素內定義要返回的類型。在 Windows Communication Foundation 中,使用數據約定定義 對這些錯誤類型進行定義。數據約定會建立將序列化到 fault detail 元素中的 XML 的結構。然後使用 [FaultContract] 指定 detail 類型,從而為操作約定加上批注。如果操作返回多個錯誤類型,則可以多 次對該操作應用 [FaultContract]。
[FaultContract] 注釋為 Windows Communication Foundation 提供了充足的信息,因此能夠在服務元數據(即 XSD 和 Web 服務描述語言 (WSDL) 定義) 中包括相應的錯誤信息,從而使客戶端生成所需的客戶端代碼來處理自定義錯誤。這樣,Windows Communication Foundation 客戶端便能使用 FaultException<T> 來捕獲用戶定義的異常。
Windows Communication Foundation 指導包提供了用於生成自定義錯誤的方案。在啟動該方案時 ,會要求您為新的錯誤類型命名,並指明是否要使用 DefaultFaultContract 基類(請參見圖 5)。
Figure 5 DefaultFaultContract Base 類
[DataContractAttribute( Namespace="http://FaultContracts/Default/DefaultFaultContract", Name="DefaultFaultContract")] public class DefaultFaultContract { int errorId; string errorMessage; Guid correlationId; public DefaultFaultContract() : this(-1, String.Empty, Guid.Empty) { } public DefaultFaultContract( int errorId, string errorMessage, Guid correlationId) { this.errorId = errorId; this.errorMessage = errorMessage; this.correlationId = correlationId; } [DataMemberAttribute(IsRequired = true, Name = "ErrorId", Order = 1)] public int ErrorId { get { return errorId; } set { errorId = value; } } [DataMemberAttribute(IsRequired = true, Name = "ErrorMessage", Order = 2)] public string ErrorMessage { get { return errorMessage; } set { errorMessage = value; } } [DataMemberAttribute(IsRequired = true, Name = "CorrelationId", Order = 3)] public Guid CorrelationId { get { return correlationId; } set { correlationId = value; } } }
默認基類提供一些與錯誤相關的常見字段,這些字段可能在異常處理方案中能夠用上。您還可 以在自定義錯誤類型中定義其他成員。方案會生成新的數據約定類型,與圖 6 所示類似。
Figure 6 新數據約定
[DataContractAttribute( Namespace = "http://CohoWinery.FaultContracts/2006/09", Name = "RegistrationError")] public class RegistrationError : DefaultFaultContract { private string registrationDetails; [DataMemberAttribute(Name = "RegistrationDetails", Order = 1)] public string RegistrationDetails { get { return this.registrationDetails; } set { this.registrationDetails = value; } } }
一旦擁有了所有的數據、消息和錯誤約定,您就可以開始定義服務約定了。
服務約定 和實現
與數據約定一樣,也存在幾種使用 Windows Communication Foundation 指導包定義服務 約定的方法。在已經擁有了需要實現的 WSDL 定義後,您可以運行方案,自 WSDL 生成服務約定。這有利 於必需 XSD 和 WSDL 協作的由 WSDL 驅動的方案。
您還可以通過運行 Windows Communication Foundation 指導包中提供的“創建服務約定”方案,從頭開始定義新的服務約定。該方案會 要求您提供 .NET 接口名稱,以及服務約定名稱(WSDL 名稱)和命名空間。同時還詢問您是否需要在服 務約定上進行會話。
圖 7創建服務約定
現在,您可以定義操作了(請參見圖 7)。對於每個操作,您都可以指定動作、請求和響應類型 (可以是數據約定類型,也可以是消息約定類型)、錯誤類型(無論是否為單向),以及在使用 Windows Communication Foundation 會話時與會話約定相關的其他詳細信息。完成操作定義後,方案將生成 Windows Communication Foundation 服務約定定義,類似於以下示例:
[ServiceContractAttribute( Namespace = "http://CohoWinery.ServiceContracts/2006/09", Name = "ClubMembershipService")] [ServiceKnownTypeAttribute(typeof(RegistrationError))] public interface IClubMembershipService { [OperationContractAttribute(Action = "RegisterNewMember")] [FaultContractAttribute(typeof(RegistrationError))] void RegisterNewMember(RegisterNewMember request); ... }
您可以運行“實現服務接口”方案來實現此服務約定。此方案會生成實現 .NET 接 口(代表服務約定)的類,並消除每種方法,如下所示:
public class ClubMembershipService : IClubMembershipService { #region IClubMembershipService Members public void RegisterNewMember(RegisterNewMember request) { throw new Exception( "方法或操作未實現。"); } #endregion }
如果為請求和響應類型選擇 XmlSerialzer 兼容類型,則方案會知道將 [XmlSerializerFormat] 屬性應用到特定操作約定中。接下來,此約定指示 Windows Communication Foundation 調度程序在運行時使用 XmlSerializer。
然後就是完成每個服務操作的實現。此處, 您可以利用“創建服務約定轉換器”方案來生成可在消息類型和業務實體類型間進行轉化的代 碼,事實上,這正是服務工廠體系結構中服務實現的主要工作。
提供服務端點
最後,為了 測試服務實現,必須對其進行托管並至少提供一個服務端點。您可以使用“主機”項目中的 “公開服務”方案來完成此操作。在運行此方案時,僅需指定服務實現類的名稱,選擇綁定類 型,並按“完成”。目前,Windows Communication Foundation 指導包僅針對主要的 HTTP 綁定(basicHttpBinding 和 WSHttpBinding)提供指導。方案會生成一個 .svc 文件,該文件引用服務 實現類,如下所示:
<%@ServiceHost language="c#" Debug="true" Service="CohoWinery.ServiceImplementation.ClubMembershipService" %>
它 還在主機的 web.config 文件內生成圖 8 中所示的 <system.serviceModel> 配置。您會發現,方 案默認啟用 WSDL 元數據檢索和 WS-Metadata Exchange (MEX) 端點。因此,此時您可以浏覽至 .svc 端 點,並查看生成的元數據。然後,您還可以在客戶端測試應用程序中運行“添加服務引用”方 案。此方案使用 MEX 查詢服務,並且需要您選擇端點。之後,方案生成用於調用所選端點的客戶端代理 代碼和配置。
Figure 8 生成的 ServiceModel 配置 (Web.config)
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name= "CohoWinery.ServiceImplementation.ClubMembershipService_Behavior"> <serviceDebug includeExceptionDetailInFaults="false" /> <serviceMetadata httpGetEnabled="true" /> </behavior> </serviceBehaviors> </behaviors> <bindings> <basicHttpBinding> <binding name="basicHttpBinding_ CohoWinery.ServiceContracts.IClubMembershipService"> <security mode="None" /> </binding> </basicHttpBinding> </bindings> <services> <service behaviorConfiguration= "CohoWinery.ServiceImplementation.ClubMembershipService_Behavior" name="CohoWinery.ServiceImplementation.ClubMembershipService"> <endpoint binding="basicHttpBinding" bindingConfiguration= "basicHttpBinding_ CohoWinery.ServiceContracts.IClubMembershipService" contract="CohoWinery.ServiceContracts.IClubMembershipService" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> </system.serviceModel>
Windows Communication Foundation 為您提供了大量選項,可 用於綁定配置、行為以及托管環境。安全性是配置過程中需要予以額外注意的一個方面。
WCF 安 全性指導包
Web 服務安全的范圍非常廣泛。WS-Security 和相關規范通過不同類型的安全令牌提 供了大量確保服務安全的方法;這提供了極大的靈活性,但同時也需要更多的安全相關指導和自動化過程 。
因此,Windows Communication Foundation 服務工廠附帶了其他針對 Windows Communication Foundation 安全性的指導包。在 Visual Studio 中打開“指導包管理器”並選擇“啟 用/禁用包”便可啟用此指導包。一旦啟用,您就可以通過指導導航器(請參見圖 9)浏覽與安全性 相關的指導。右鍵單擊“主機”項目時,會出現一個名為“服務工廠 - 安全性” 的新上下文菜單。
圖 9WCF 安全性方案
如您所見,可以通過幾種方案對最常見的安全性模式和實施方案 進行自動化,包括通過將 Windows 帳戶、SQL Server™、或 Active Directory® 應用程序模 式 (ADAM) 用作身份存儲來進行相互身份驗證、Kerberos 和直接身份驗證。另外,也可以使用匿名身份 驗證的安全方式,采用此方法時,消息是通過服務器證書進行保護,而且不需要客戶端身份驗證。
我們來看一個常見的方案:使用 SQL Server 進行直接身份驗證。在運行方案時,首先會看到的 是向導。向導的第一個屏幕描述了此特定方案實現的安全性模式,並提供了到 p&p 網站的鏈接,該 網站中有模式的詳細描述。向導的其余部分對指定 Windows Communication Foundation 端點、綁定與行 為的詳細信息,以及指定要使用的服務器證書、要求的消息保護級別和 SQL Server 角色提供程序詳細信 息整個過程進行了自動化。在向導完成時,“主機”項目的 web.config 文件中生成了相應的 Windows Communication Foundation 配置,可隨時使用。其他安全性方案的使用也是非常簡單。
一旦確保了服務的安全,下次在客戶端應用程序中運行“添加服務引用”方案時,安全性設置 將導入到客戶端配置中,而且方案可能向您詢問其他詳細信息,如憑據。
這類安全自動化意義非 凡。它使結構設計師和開發人員了解他們遵循的是可靠的安全模式和實施方案。隨著 Windows Communication Foundation 指導包的不斷發展,安全性方面無疑也會不斷的改進和加強。
自定義 安全性選擇
盡管安全性方案提供了相當有用的自動化,但開發人員仍必須首先選擇適當的安全性 方案。這樣做之後,在實施特定方案期間,仍需要做出一些選擇。作為結構設計師,為了進一步簡化過程 並推行您自己的安全性標准,您或許打算對開發人員的選擇進行約束。
Windows Communication Foundation 安全性指導包提供了用於修改可用安全性設置的方案,這樣,您 便能將設想付諸實施。右鍵單擊解決方案,選擇“服務工廠 - 安全性”,然後“修改”安全性設置,這 樣會打開一個向導,指引您縮小用戶可用的安全方案的范圍。例如,如果您僅想讓開發人員使用 Kerberos 或 X.509 憑據,僅需取消選擇其他選項即可。您也可以約束消息保護級別選項。例如,如果您 僅想讓開發人員使用“簽名”和“加密”選項,請取消選中其他選項。
一旦設置完成,向導將更新解決方案配置,從此時起,指導包僅允許使用您指定的安全性選項。例如 ,如果您返回到“指導導航器”或“服務工廠”上下文菜單,則列表中僅顯示 Kerberos 和 X.509 方案 。而且,在實施可用的方案之一時,僅有“簽名”和“加密”選項會出現在消息保護選項中。
在需要確保工具包之間的互操作性時,安全性選擇顯得非常重要。因此,為了進一步簡化常見的互操 作方案,請考慮 Windows Communication Foundation 安全性指導包提供了另一個向導,用於通過所設想 的特定互操作性方案約束安全性選擇。可以通過從解決方案上下文菜單中選擇“修改”互操作設置來啟動 該向導。
如果系統需要確保所有 Windows Communication Foundation 服務都可由 Web Services Enhancements (WSE) 3.0 客戶端調用而且不會失敗,您僅需讓開發人員看見 Windows Communication Foundation 安全性選項即可。您可以通過選擇 WSE 3.0 | Windows Communication Foundation 選項完 成此項操作,您還可以進一步約束兩個工具包都支持的單個規范的相關安全性選擇。然後,在您下次運行 安全性方案時,只有指定的選擇才可用。最終,將有更多的互操作性方案得到支持(即使是像“由 BEA WebLogic Portal 9.2 客戶端使用的 Windows Communication Foundation 服務”之類的方案)。
以上兩個向導都會生成名為 SecurityConfiguration.xml 的文件,該文件與解決方案相關聯。此文件 告知 Windows Communication Foundation 安全性指導包哪些選項可用。也可將此文件作為自定義指導包 的一部分進行重新部署,以確保每個人都能夠看見相同的選項。
高級自定義
在我看來,Microsoft 軟件工廠計劃的核心是為各組織創建自定義指導包。能夠將 p&p 開發的常 見方案與用戶特定於域的方案結合使用,這無疑具有強大的吸引力。盡可能實現常見任務的自動化最終將 對各組織的生產力、質量、一致性和可預見性產生積極的影響。
正如您在這幾期專欄中所了解到的,ASMX 和 Windows Communication Foundation 指導包支持一些簡 單的自定義,例如修改解決方案結構、重新分配項目職責,以及修改由軟件包確定可用的安全性/互操作 性設置。但是對於更高級的操作,您就需要熟悉 Guidance Automation Toolkit (GAT),並了解如何創建 和部署自己的指導包。
Web 上有些相關的文章和資源可幫助您進一步了解 GAT。然而,如果您已經安裝了 ASMX 服務工廠, 那麼您可找到一個詳細的文檔,該文檔中描述了創建新指導包的分步過程。文檔名為“How to:Create a New Guidance Package that Includes your Configuration Settings”(如何創建包含自己的配置設置 的新指導包)。如果您對高級自定義感興趣,請確保先閱讀此文檔。
總結
Windows Communication Foundation 的服務工廠為亟需指導的 .NET Framework 3.0 新興領域提供了 許多有價值的指導資產。Windows Communication Foundation 指導將幫助您更快速地開發符合所接受安 全性模式的 Windows Communication Foundation 服務。查找 .NET Framework 3.0 發布期間的官方發布 版本。
最終版本很有可能提供一些本文未涉及的新功能,例如對約定設計(數據、消息和服務)、約定版本 控制、消息驗證、部署、處理大型消息的指導,甚至可能包括將工作流並入到 Windows Communication Foundation 服務實現中的模式。他們還致力於開發另一項功能 - 驗證特定服務配置的安全性設置(類似 於 WSE Policy Advisor)。在本專欄發布時,其中許多功能可能已經完成。
如果您對本文有任何反饋或對未來功能有任何建議,請參與到 GotDotNet 的服務工廠社區中。有關詳 細信息,請參閱“其他參考”提要欄。