WCF4.0 进阶系列第一章 WCF简介
第一章 WCF簡介
1. 什么是WCF
如果你閱讀本書的目的是為了解如何使用WCF構建分布式應用程序和服務,那么什么是WCF,為什么使用WCF?該如何使用WCF? 回答這些問題,讓我們來回顧一下歷史。
(1)早期個人電腦時代的應用程序
個人電腦時代,業務解決方案由一套應用程序組合而成。一般會包含文字處理程序,電子表格處理程序,和數據庫套件。有經驗用戶能夠把業務數據存貯在數據庫中,然后使用電子表格分析數據,并創建基于數據的報表與文檔,或利用文字處理軟件寫分析報告。這些程序往往安裝在同一臺電腦上,并且其數據和文件格式只為其所有。這就是典型的桌面應用程序平臺,其特點是僅供單個用戶使用,并且只在很小范圍內處理多任務。
隨著個人電腦的價格逐漸便宜并且廣泛地作為商業工具,應用程序面對的挑戰是如何面對多個用戶之間數據的共享。它并不是一個全新的挑戰,因為多用戶數據庫已經開始面世一段時間,但是多用戶數據庫是運行在大型計算機而非個人電腦上。很快,基于網絡的解決方案和網絡操作系統出現在個人電腦平臺上,使得同一個機構內部部門間的電腦均連接到網絡中,并且在網絡里共享其資源。而且,數據庫廠商也很快開發出獨立于大型機的的數據庫管理軟件,它可以運行在網絡中的個人電腦上,其結果,人們開始利用這些軟件或方案便利地共享業務數據。
(2) 進程間的通訊技術
網絡平臺僅僅是整個故事的一部分。 雖然基于網絡的方案允許個人電腦之間相互通訊、共享打印機和磁盤;但是程序還需要和運行在其他個人電腦上的程序之間發送數據、接收數據以及互操作。許多常見的進程間的通迅機制開始逐步應用,比如named pipes和sockets。 這些技術在當時使用率十分低下,因為要掌握它們,你必須很好的理解網絡。如今這種境況仍舊一樣。比如,使用socket創建收發送數據的應用程序的職位仍舊是一個富有挑戰的工作崗位。表面上,進程相當簡單,但是并行訪問是一件相當復雜的事情。隨著計算機和網絡的不斷進化,進程間通訊的種類和能力也相應變化。比如:微軟開發了COM技術使Windows平臺上應用程序和組件之間可以相互通訊。開發人員能夠使用COM創建可復用的軟件組件,連接多個組件構建程序,或利用Windows服務。微軟自己也使用COM技術使自己的程序作為服務的組件用以構建各種方案。
微軟設計COM的最初想法是解決同一計算機上應用程序和組件之間通訊。后來,微軟推出了DCOM,也稱作分布式COM,它使應用程序可以訪問網絡中其他計算機上的組件。再之后,DCOM發展為COM+。COM+包含很多特性,比如與微軟分布式服務器集成,使程序能將一系列的操作放在一個組中,并使該組操作以事務的方式與組件相互通訊。COM+還具有自動管理資源(比如你使用一個組件連接到數據庫,你能確保當程序使用完組件后,組件會自動關閉該數據連接)和異步操作能力。COM+后來被.NET Framework替代。.NET Framework不僅擴展了COM+, 而且提供很多新功能(Remoting:使客戶端應用程序像訪問本地對象一樣的方式訪問位于遠程服務器上的對象)。微軟將此項技術命名為企業服務。
(3) Web與Web服務
COM,DCOM,COM+,企業服務,.NET Framework Remoting在局域網上運行的非常不錯,并且它們都能運行在Windows操作系統之上。
然而,當微軟推出COM和DCOM的時候,萬維網出現了。萬維網是基于互聯網,其已經經過數十年的發展。萬維網提供了一個架構,開發人員使用此架構,利用位于世界各地的組件和其他元素構建應用程序,而且這些應用程序能運行在不同計算機體系下。第一代web應用程序非常簡單,僅僅由一些靜態網頁組成;用戶可以使用本地計算機上的網絡瀏覽器下載并查看這些頁面。第二代web應用程序提供給開發者一些可編程的元素(組件或者插件),用戶從web站點下載然后在本地計算機的瀏覽器上計算出結果。第三代則推出了web服務。 Web服務是一個應用程序或者組件,其在服務器端運行。Web服務能接收來自客戶端程序的請求,在服務器端運行,然后將結果返回給發出請求的客戶端。Web服務還可以訪問另外一個位于互聯網上Web服務。這就是全球的、分布式的程序。
你可以通過visual studio和.NET Framework創建基于Windows的web服務。當然你也可以使用其他技術創建運行在非Windows平臺的web服務。盡管web服務不限定某種語言或者平臺。創建一個分布式的、全球性的web服務,開發人員必須遵循一些原則,其包括數據的格式,發送和接收消息的協議,安全處理方式。這些特性都是與平臺無關的。
(4) 使用XML作為通用的數據格式
不同的計算機能使用其內部的表現形式存貯相同的值。比如:最高字節位在前的32為處理器與最低字節位置在前的32為處理器,它們使用不同的數據格式,但是可以存貯相同的值。因此,為了保證同一個程序在不同的計算機上的共享數據,開發人員必須統一采用一種與計算機體系無關的數據存貯格式。簡而言之,xml是目前大家認可的數據存貯格式。 Xml是基于文本的、易讀的、簡單標記描述各種類型的數據的可擴展標記語言。
<Person><Forname>John</Forename><Surname>Sharp</surname></Person>
不需要費力,你就能猜測到此數據秒速的實際意義。一個需要發送信息的程序可以利用這個格式將Person的信息發送給另外一個程序;接收方可以接收Person信息,并將其轉化為有意義的數據。當然上面的數據格式也可以改成成如下:
<Person Forname="John" Surname="Sharp" />
這里有其他很多種可能的格式變化。應用程序如何知道其格式能被其他的程序正確地識別?答案在于兩個程序都統一采用同一種數據結構。這個數據結構就是xml schema。Xml schema是用來描述xml文檔的結構,發送方利用其來描述發出信息的結構;接收方利用其將接收到的信息轉化為有意義的數據。
(5)接收與發送Web服務請求
通過使用xml和xml schema格式化數據,web服務和客戶端之間可以相互收發數據,前提是客戶端與web服務端必須采用統一的發送和接收請求的協議。此外,客戶端能識別自己發送的消息和從web服務端返回的消息。
簡而言之,web服務和客戶端程序通過使用SOAP協議進行通訊。SOAP協議定義了如下幾個方面:
SOAP消息格式
輸入如何編碼
如何發送消息
如何處理返回的消息
Web服務能發布WSDL文檔,其是一個xml文檔,描述該web服務可接收的消息以及如何響應客戶端傳遞過來的消息。客戶端程序能使用這些信息來決定如何與該服務進行通訊。
(6)JavaScript對象和RIA
XML/SOAP模型用以定義和傳播可交換消息的格式,這非常容易理解。但是在某些情況下,此模型顯得比較復雜。因為此模型會產生大量的冗余,特別是在傳送和接收數據比較小的情況下。對于當今流行RIA就是一個典型的例子。
RIA是一種近似于傳統桌面應用軟件系統功能,但實際上是通過web瀏覽器與遠程服務器進行交互的網絡應用系統。為了提供桌面交互功能,RIA使用JavaScript和AJAX。許多廠商提供相應的架構,比如微軟的Silverlight,開發人員使用Silverlight可以快速且便利地實現RIA。
盡管XML是AJAX技術的一部分,輕量級的原生的JavaScript格式被用以表示對象并且用戶和網絡間的傳輸。這種格式就是JSON。雖然它的名字與JavaScript有關,但實際上JSON是語言無關的一種格式;大部分程序員一眼就看明白它。JSON通過名稱/值來描述數據。比如:{"forename":"John","surname":"Sharp","Age":46} .
你可以通過代碼的方式直接讀寫JSON數據。但是大多數開發人員喜歡使用JSON轉換器自動地將其他格式的數據轉化成JSON,尤其當源數據結構非常復雜的時候。現代大多數語言都提供JSON轉化器來創建分布式應用程序,比如WCF。
JSON與XML最大的不同在于XML是一個完整的標記語言,而JSON不是。這使得XML在程序判讀上需要更多的氣力。主要原因在于XML的設計理念與JSON不同。XML利用標記元素的特性提供絕佳的擴展性;而JSON的重點在于數據的交換。
(7)全局環境下的安全和隱私的處理
安全用以識別用戶和服務,然后授權其訪問相應的資源。在分布式環境中,安全性有非常重要的影響。在與網絡環境隔離環境、或桌面應用程序環境中,可以通過物理的安全方式來保護非法用戶通過鍵盤輸入或者查看顯示屏的內容;而在網絡環境中,物理安全保護措施是不充分的。在網絡環境下,你需要確保合法用戶能夠訪問共享資源、數據和運行在網絡環境中的組件。系統提供商比如微軟推出包含許多安全特性的操作系統。一般情況下,這些安全特性包括維護一個用戶列表,憑據【用以建立自己的標識,比如密碼】。這些安全特性在一個組織內部工作非常好。但是,當你在互聯網公布服務時,很顯然記錄所有用戶和計算機的身份和憑證信息是一件不可行的事情。
經過大量關于安全性方面的調查和研究,提出了許多解決方案。為了保證服務端和客戶端通訊的安全,兩者需要采用統一的安全機制,在該機制下,雙方可以識別和驗證對方。OASIS是提出許多實現安全標準的聯合組織,比如用戶名/密碼,X509證書,和Kerberos口令。如果一個服務提供保密信息的訪問,需要考慮使用上述安全標準中的一種。
隱私與安全緊密相關,并且同等重要,特別是你的服務提供基于互聯網的訪問。你不希望非授權用戶破譯和讀取客戶端程序和服務之間的消息。為了達到這個目的,服務和客戶端必須隱藏兩者之間的對話。一般來說,通過加密需要交換的消息的來保證隱私性。有多種加密方式可供選擇,最廣泛的加密方式是通過公鑰與私鑰來實現對消息的加密。
在服務和客戶端之間實現加密和安全并不是一件容易的任務。幸運的是在.NET Framework下,微軟引入了WSE,其作為 visual studio的一個插件,使得程序員能夠非常便利的創建安全的服務,并且簡化了服務和客戶端的配置。
(8)SOA架構與WCF
軟件開發人員很快意識到web服務的原則應采用一種更通用的方式—"軟件作為服務",并且開始傾向與實現面向服務的架構。SOA背后的驅動力是實現競爭力和效益性—業務解決方案應該能快速適應業務環境的變化。SOA架構的主要原則是:在任何地方重用現存的軟件,并且將這些軟件對外公開為服務。
服務提供了一系列實現預定義的操作,以實現公司的業務邏輯。 開發人員通過調用新的或現存的軟件實現這些操作;或者通過組合現存的軟件滿足企業的業務需求。服務創建者對外隱藏了實現的細節,對內創建者可以顯示地調用其他應用程序或服務來實現該其想要的功能。實現一個服務包含下列關鍵因素:
基于預定的標準提供可重用、可擴展的接口,最大化互操作
提供可擴展的主機環境,在此環境下,服務能快速響應用戶請求,甚至面對大量用戶請求時也可以快速響應。
WCF提供一個模型,使用該模型,你可以實現符合大部分大眾認可的標準,包括SOAP,XML和JSON。此外,WCF還支持其他Windows平臺上特有的技術比如MSMQ,并對這些標準提供了一個統一的編程模型。這樣,你可以創建盡可能獨立的五福,而無須掌握底層服務和客戶端之間連接機制。使用WCF,你可以兼容早期的相關技術,比如WCF客戶端可以訪問你使用WSE創建的web服務。
Windows為SOA提供了一個可擴展的,安全的,健壯的平臺。Windows 2008 Server對上述特性做了進一步地優化。你可以構建可擴展的Windows Server簇,充分利用現有的便宜的硬件。另外一方面,如果你不想自己折騰硬件,你還可以在Windows云平臺上實現基于SOA的服務。
Windows Azure是一個云計算平臺,通過微軟數據中心提供按需計算和存儲設備。你可以在本地構建和測試服務,完后上傳該服務到數據中心上一臺或多臺虛擬機,這些虛擬機運行在由微軟員工管理和維護的計算機上。你可以設定參數,當訪問需求增加時擴展你的服務到多個計算機上;反之當訪問需求減少是,是使用的計算機數量減少。Windows Azure提供高可靠連接架構,其允許客戶端應用程序定位并調用你的服務。此連接利用了WCF相應的特性。
2. 構建一個WCF服務
Visual Studio 2010為創建WCF服務和客戶端應用程序提供了完美的開發環境。其提供了創建WCF服務的項目模板。你可以使用該模板創建一個簡單的WCF服務,該服務可以對外提供查詢和維護數據庫的方法。本書中使用的數據庫是SQL Server 2008自帶的AdventureWorks OLTP數據庫。
AdventureWorks公司生產自行車和自行車配件。其數據庫包含了產品信息、銷售信息、客戶信息和員工數據。在本章的練習中,你將創建一個包含下列操作的WCF服務:
列出所有銷售的產品
獲取產品的詳細信息
查詢某個產品的存庫
修改某個產品的庫存
這些練習所需的數據存儲在AdventureWorks數據庫的Product和ProductInventory表中。圖表1-1列出了這兩張表及其它們之間一對多的關系:即一條產品記錄對應多條存貨記錄。這是因為一個產品可以存貯在一個或者多個倉庫中。他們之間通過ProductID來建立一對多的關系。
為了簡化讀取數據庫的代碼,你將使用ADO.NET實體框架。它是.NET Framework 4.0的一部分并與Visual Studio 2010一起發布。實體框架的目的是將數據庫的數據表轉化為一系列的對象,以供開發人員在程序和服務中使用。使用實體框架,指定數據庫中的一個表,創建一個實體模型,并生成一個對象模型;利用該對象模型,你可以對該表進行查詢,插入,更新和刪除操作。使用實體框架的最大優點是你不用關心具體的數據庫管理系統、你可以讀取數據而不需要掌握數據庫管理系統是如何工作的(你甚至都不必了解SQL)。
(1)為WCF服務創建實體模型
啟動visual studio 2010并創建一個C#類庫的新項目,然后刪除class1.cs
添加一個新的ADO.NET實體數據模型到你的項目中
在添加模型向導中,在選擇模型內容頁面,點擊"從數據庫生成模板",然后點擊下一步
選擇你的數據庫連接,如果為空,請創建一個新的連接.這一步,很簡單,略過
在選擇數據庫對象頁,選擇product和productionInventory表,并且選中"生成數據的對象使用單數或者復數名稱"
點擊完成,你將建立一個數據庫實體模型。
(2)創建名為ProductsService的WCF 服務
Visual Studio提供了多個WCF Service模板. 此時你使用的模板創建的是一個基于Web的WCF Service。在隨后的章節中,你將會了解到如何實現其他方式的實現WCF服務,比如在一個類庫中,在單獨的程序中,在WF中。
WCF Service模板將會生成一個默認的服務(在本示例中,分別為Service.svc, IService.cs和Service.cs)。同時還會在web.config中添加system.serviceModel節點及子節點配置)。在Service.cs文件的頭部,我們發現引用了using System.Collections.Generic,using System.Linq和using System.Text命名空間;同時還引用了using System.ServiceModel和using System.ServiceModel.Web命名空間。
System.ServiceModel命名空間包含了供WCF用來定義服務和服務所對應的操作。隨著本書的深入,你將會了解到該命名空間下許多其他的類和類型。WCF使用using System.Runtime.Serialization命名空間來將對象序列化為各種供網絡的傳輸的數據流;反之,還用來將流反序列化成對象。關于序列化和反序列化,將在后續的章節中介紹。System.ServiceModel.Web命名空間包含了用來創建REST Web服務的所需的類型。關于REST Web服務,將在15章介紹。
Service.cs定義了一個簡單的WCF服務。該服務提供了GetData和GetDateUsingDataContract方法。目前,我們不需要關注這兩個方法的細節,我們需要注意的是該實例是告述我們如何實現服務所包含的操作。 在一個WCF服務中,一個操作就是一個方法,它接收0個或者多個參數,并返回值。當一個客戶端應用程序向該服務發送消息,WCF運行時將把該消息傳遞到對應的方法,并且將消息中的數據傳遞給該方法。類似地,當方法返回值時,返回值將被包裝到一個消息中,然后回傳給客戶端程序。
Service.cs實現了IService.cs接口。IService接口簡單的定義了GetData和GetDateUsingDataContract方法,它們在Service.cs中具體實現。這個接口就是服務協定,它通過ServiceContract和OperationContract屬性來實現。IService.cs同時還包含一個名為CompositeType的類,其使用了DataContract和DataMember屬性;CompositeType就是數據協定。
WCF服務架構采取了"協定優先"的開發方式。 當執行該開發方式,你定義接口(協定),服務實現該接口,然后構建一個符合這些接口(協定)的服務。 這不是一項新的技術,COM開發者在數十年前就已經熟悉該策略。"協定優先"開發方式讓開發人員把注意力放在服務的設計上。如果有必要,服務的設計能夠快速的審核,以確保其不會開發人員不用太關注其實現的細節。請注意,在大多數情況下,客戶端程序不要采用WCF實現,即使該程序運行在Windows平臺上。
在解決方案中添加一個名為ProductsService的WCF Service類型的網站。
定義協定。 重命名IService.cs和Service.cs。將他們分別命名為IProductsService.cs和ProductsService。然后添加如下代碼:
View Code
[ServiceContract]
public interface IProductsServcie
{
[OperationContract]
List<string> ListProducts();
[OperationContract]
ProductData GetProduct(string productNumber);
[OperationContract]
int CurrentStockLevel(string productNumber);
[OperationContract]
bool ChangStockLevel(string productNumber, short newStockLevel, string shelf, int bin);
}
實現服務
View Code
public class ProductsService : IProductsServcie
{
public List<string> ListProducts()
{
List<string> productsList = new List<string>();
try
{
using (AdventureWorksEntities database = new AdventureWorksEntities())
{
var products = from product in database.Products
select product.ProductNumber;
productsList = products.ToList();
}
}
catch(Exception ex)
{
throw new SystemException(ex.Message);
}
return productsList;
}
public ProductData GetProduct(string productNumber)
{
ProductData productData = null;
try
{
using (AdventureWorksEntities database = new AdventureWorksEntities())
{
Product matchingProduct = database.Products.First(
p => String.Compare(p.ProductNumber, productNumber) == 0
);
productData = new ProductData() {
Name = matchingProduct.Name,
ProductNumber = matchingProduct.ProductNumber,
Color = matchingProduct.Color,
ListPrice = matchingProduct.ListPrice
};
}
}
catch
{ }
return productData;
}
public int CurrentStockLevel(string productNumber)
{
int stockLevel = 0;
try
{
using (AdventureWorksEntities database = new AdventureWorksEntities())
{
stockLevel = (from pi in database.ProductInventories
join p in database.Products
on pi.ProductID equals p.ProductID
where String.Compare(p.ProductNumber, productNumber) == 0
select (int)pi.Quantity).Sum();
}
}
catch
{ }
return stockLevel;
}
public bool ChangStockLevel(string productNumber, short newStockLevel, string shelf, int bin)
{
try
{
using (AdventureWorksEntities database = new AdventureWorksEntities())
{
int productID = (from p in database.Products
where String.Compare(p.ProductNumber, productNumber) == 0
select p.ProductID).First();
ProductInventory productInventory = database.ProductInventories.First(
pi => String.Compare(pi.Shelf, shelf) == 0
&& pi.Bin == bin
&& pi.ProductID == productID
);
productInventory.Quantity += newStockLevel;
database.SaveChanges();
}
}
catch
{
return false;
}
return true;
}
}
配置和測試服務.
你需要為WCF service提供一個主機環境,并且設置好相應的配置文件。其配置文件告訴host哪一個class包含了WCF服務以及如何偵聽來自客戶端的請求。WCF提供了一個默認的配置文件,其內容覆蓋了大部分上述配置信息。在后續章節中,你將會了解到更多相關內容。
設置Service.svc
|
<%@ ServiceHost Language="C#" Debug="true" Service="Products.ProductsService" CodeBehind="~/App_Code/ProductsService.cs" %> |
設置web.config(創建Service時,已經自動添加了下列內容)。關于<system.serviceModel>配置信息,后續章節中將做詳細介紹。
View Code
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
因為使用了ADO.NET實體模型,所以需要將ProdcutsEntityModel中的數據庫連接字符串copy到web.config中
View Code
<connectionStrings>
<add name="AdventureWorksEntities" connectionString="metadata=res://*/ProductsModel.csdl|res://*/ProductsModel.ssdl|res://*/ProductsModel.msl;provider=System.Data.SqlClient;provider connection string="data source=localhost;initial catalog=AdventureWorks;integrated security=False; user id=ap_wcf; password=ap_wcf; multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
Ok,保存web.config.右鍵點擊service.svc,選擇瀏覽,確認你的服務正常工作。(如果你想部署一個WCF Service且不創建*.svc文件,請參考dudu文章)
(4)創建WCF服務客戶端
創建一個控制端應用程序
引用WCF服務:在bin上右鍵添加服務引用或者通過visual studio菜單"項目-添加 服務引用"
服務引用文件夾將會自動出現該項目中。如果你展開該文件夾,你將會看到ProductsService的實體。服務引用包含一個代理類。你可以看到代理類的代碼,如果你選擇了現實所有項目文件選項。
同時,添加服務引用時,將會自動為項目添加app.config。它包含了調用WCF服務所需的一些信息。
View Code
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IProductsServcie" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:2003/ProductsService/Service.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IProductsServcie"
contract="ProductsService.IProductsServcie" name="BasicHttpBinding_IProductsServcie" />
</client>
</system.serviceModel>
WCF客戶端程序與服務端不一樣,沒有使用默認的配置文件。因為客戶端的配置文件比服務器端的設置要多一些。
<client>片段用來設置客戶端如何連接到服務端。<endpoint>元素提供了供客戶端調用的服務端的細節信息。一個端點包含三個必須屬性:地址,綁定和服務協定。 其他可選項中,端的的名稱值得注意,因為當你的客戶端程序連接到多個服務時,每個服務在客戶端的配置文件中,都可以有自己的名稱以區別其他的服務。
地址是服務端WCF服務的URL地址。
綁定元素用來設置訪問Web服務的傳輸機制,采用的協議和其他項目。一個服務可以使用WCF內建的一種綁定類型。在本例中,你可以不指定任何綁定,因為WCF服務會采取默認的綁定—basicHttpBinding。該綁定是基于HTTP協議,并與之前版本的非WCF 服務兼容。你可以修改一個綁定的屬性以提供額外的信息,比如延遲,消息加密方式和安全性。 本例中,當你引用web服務時,自動添加了一個名為BasicHttpBinding_IProductsServcie的綁定設置。該設置會根據客戶端端點的不同而變化。也就是說bindingConfiguration的具體內容與端點的細節密切相關。一定要根據端點來設置相應的內容,否則客戶端和服務器端不能夠正常地通訊。
協定元素指向服務的協定。在本地例中,該屬性的值為ProductsService.IProductService.
調用ListProducts的方法
static void Main(string[] args)
{
ProductsServcieClient proxy = new ProductsServcieClient();
Console.WriteLine("Test 1: List all products");
string[] procutNumbers = proxy.ListProducts();
foreach (string productNumber in procutNumbers)
{
Console.WriteLine("Number: {0}", productNumber);
}
Console.ReadLine();
}
類似地,調用其他方法。
最后,生成解決方案,并運行客戶端序。并確認測試的結果與你預計的結果一致。
3. WCF和SOA基本原則
在本章一開始提到,WCF是實現SOP的完美平臺。
從前面的例子中,使用WCF,你可以創建服務,并集成到企業的項目中去。你可以不用編寫新的代碼,就將現有的應用程序集成到WCF服務中去。在WCF出現之前,實現這個功能是相當困難的。WCF能夠非常便利地把程序和組件"粘合"在一起。此外,WCF可以使用標準的協議,數據格式,通訊機制,還可以與通過其他技術創建的服務進行互操作。
SOA是網絡上一系列的資源,它們作為相互獨立的服務而存在,彼此之間可以相互訪問且不需要知道服務實現的細節。你可以將這些服務組合在一起形成一個SOA,用以創建企業應用。這里,我并不會涉及SOA的整個理論,但是SOA的主要好處在于可以創建與平臺和位置無關的復雜應用。這意味著,你可以迅速的升級一個服務或者遷移一個服務到另外一個站點。只要服務對外暴露與此前服務同樣的接口,這樣你就可以繼續使用該服務而不需要修改任何代碼。但是,SOA并不是一個可以直接解決分布式應用架構的魔杖。為了成功的設計和實現SOA,你需要注意"面向服務的四個基本原則":
明確邊界。服務和應用程序通過相互發送消息進行通訊。你不應該假設一個服務如何處理一個請求,或者一個應用程序如何處理響應。準遵循此原則,能夠移除服務和應用程序之間的依賴關系。此外,發送和接收消息都是有代價的。在你設計服務端的服務是應該考慮到這點,而且盡量減少客戶端與服務端的之間的通訊。
服務是自治的。如果你創建一個基于服務的應用程序,你不一定能控制你所使用的每個服務,即使該服務寄宿于你的組織之內。Web服務的位置可能發生改變,或者一個服務由于維護或者其他原因臨時離線。你應該設計一個松耦合的架構,這樣你的程序是可以自動容錯,即使有一個服務不可用而你的客戶端程序依然可以運行。
服務共享數據結構和協定,而非類和類型。 服務對外發布操作以及收發數據結構的信息。客戶端使用這些信息與服務端進行通訊。你應該使用協定和數據結構來定義你對外的服務。這將會減小客戶端程序對某一個版本服務的依賴。服務可能會隨著時間而演變,一個新版本的服務可能會替代之前版本的服務。如果一個服務更新,那么該服務應該對現有的客戶端保持兼容性,該兼容性包括先前實現的協定和構成消息的數據結構。如果你修改一個服務,使其提供其他的功能,你可以添加協定和數據結構以擴展你原有的服務,且保留之前的協定和數據結構。這樣,舊的客戶端不需要做任何改變仍可以訪問更新后的服務。
兼容性是基于策略的。數據結構和協定定義了服務的"形狀",而非客戶端訪問服務端所需要的非功能性需求。比如,一個服務可能有安全性方面的需求,其規定客戶端必須某種方式連接到服務端,并且收發的消息必須以某種方式進行加密。這就是一個策略。策略方面的需求不能通過協定來指定,而且不應該要求在客戶端或者服務器端進行額外的編碼。而且這些策略還可能隨時變化,因此它應該從服務的實現和客戶端解耦出來。你服務的具體實現應該和策略是相互獨立的,而且你應該強制客戶端遵守服務器端策略的要求。此外,所有的服務和客戶端應該在策略方面達成統一。
4. 總結
本章為你介紹了WCF。你應該已經熟悉WCF的目的,如何通過"協定優先"的方式創建一個簡單的Web服務;在IIS上部署一個WCF服務S,并且創建一個客戶端應用程序訪問WCF服務。最后,你還了解到SOA的基本原則。而且理解了使用WCF你可以快速地創建一個基于SOA的服務。
本章源文件下載
總結
以上是生活随笔為你收集整理的WCF4.0 进阶系列第一章 WCF简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 文件的保存与使用电脑如何保存文件
- 下一篇: 怎么才能使路由器不掉线如何设置路由器不掉