SOA架構開發
SOA介紹
1、什么是SOA
SOA是:面向服務的體系結構(Service Oriented Architecture)指的是一個系統的架構,他的研究領域是大型分布式系統的“架構”范式。而OOP指的是程序具體開發過程中的“編程”范式。再通俗一點說就是在一個具體的軟件內我們談論OOP,但是在討論軟件與軟件,系統與系統的關系的時候我們會借助SOA的理念幫助我們處理他們(指各個系統)之間的關系。
2、SOA的核心理念
支持異質(異構)
不要奢望企業中的每個系統都是java平台的,不要奢望企業中的每個系統都運行在Window平台上,不要奢望企業中的數據庫都是結構化的……隨着時間的流逝老版本的系統依在(里面的數據是無價的,別跟我說可以重新開發一套新系統,然后把舊系統的數據導出來,這就相當於讓一個環境的某個物種短時間內重新進化,夢一樣幼稚的想法!)新系統層出不窮,SOA要做的就是在這些異質(異構)的系統之上保證他們的“和平相處”。
支持變化
SOA絕不是一次性的事件,隨着企業的發展要在系統環境的變化中產生出具有自己風格的SOA,這次整合了新舊系統興許不就的將來,一次公司的收購就會迎來新的一輪SOA過程。
松耦合
目的是保證整個系統的靈活性和可伸縮性。
並且:
SOA中,服務之間應保持獨立。更改一個服務不能影響到服務的調用。
SOA由一些通過標准消息通信的服務組成,標准消息機制讓他們彼此獨立。服務之間應該能進行異步通信。服務應該提供安全的通信和可靠的消息服務。
3、企業服務總線ESB
企業服務總線(Enterprise Service Bus)是SOA的基礎設施,用於保證消費者能夠調用供應者提供的服務。
ESB的核心作用
數據格式轉換
因為SOA是支持異質的,所以ESB主要的作用就是處理不同平台不同語言之間的相互調用。那么首先要做的就是數據格式的轉換。
引入一個中間格式然后將不同平台中的API都映射到這種格式上來。大多數情況人們選擇的是和平台無關的WebServices技術,於是SOAP也就成為了這種中間格式。
(智能)路由
不同優先級的消息,不同類型的消息是需要給予不同處理。從這個角度說ESB就不單單是一個傳遞消息的通道了,還需要有一套自己的能識別其他服務提供數據方法。關於智能路由的另一個作用就是負載均衡。
ESB的各個職責都是“提供互操作性”這個核心任務的擴展。很明顯異質系統通過ESB“連接”到了一起,並且支持“互操作”那么原有系統的安全是一個很大的問題。還需要注意的是不同協議提供不同形式的可靠性,例如WebServices中的HTTP協議無法保證消息傳遞的成功(周所周知HTTP協議是無連接、無狀態的)。隨着SOA的范圍增大,連接到ESB上的系統增多時高效的管理服務將成為ESB最棘手的問題。
Web服務(Web Service)
1、什么是Web Service
Web Service就是基於Web的服務。它使用Web(HTTP)方式,接收和響應外部系統的某種請求。從而實現遠程調用。
它由SOAP--WebService之間的基本通信協議、WSDL--WebService描述語言兩部分組成。
Web Service的設計是為了解決不同平台,不同語言的技術層的差異。使用Web Service無論使用何種平台,何種語言都能夠使用Web Service提供的接口,各種不同平台的應用程序也可以通過Web Service進行信息交互。
Web Service還具有以下特性:
實現了松耦合
應用程序與Web Service執行交互前,應用程序與Web Service之間的連接是斷開的,當應用程序需要調用Web Service的方法時,應用程序與Web Service之間建立了連接,當應用程序實現了相應的功能后,應用程序與Web Service之間的連接斷開。應用程序與Web應用之間的連接是動態建立的,實現了系統的松耦合。
跨平台性
Web Service是基於XML格式並切基於通用的Web協議而存在的,對於不同的平台,只要能夠支持編寫和解釋XML格式文件就能夠實現不同平台之間應用程序的相互通信。
語言無關性:無論是用何種語言實現Web Service,因為Web Service基於XML格式,只要該語言最后對於對象的表現形式和描述是基於XML的,不同的語言之間也可以共享信息。
描述性
Web Service使用WSDL作為自身的描述語言,WSDL具有解釋服務的功能,WSDL還能夠幫助其他應用程序訪問Web Service。
可發現性
應用程序可以通過Web Service提供的注冊中心查找和定位所需的Web Service。
Web Service也是使用和制作分布式所需的條件,使用Web Service能夠讓不同的應用程序之間進行交互操作,這樣極大的簡化了開發人員的平台的移植難度。
2、Web Service體系結構
Web Service由服務提供者和服務消費者組成。
服務提供者也可以稱為服務的擁有者,它通過提供服務接口使Web Service在網絡上是可用的。服務接口是可以被其他應用程序訪問和使用的軟件組件。
服務請求者也稱為Web Service的使用者,服務請求者可以與服務提供者進行通信。相對於Web Service而言,服務請求者是尋找和調用提供者提供的接口的應用程序。
3、Web服務協議棧
在Web Service體系結構中,為了保證體系結構中的每個角色都能夠正確和執行Web Service體系結構中的發布、查找和綁定操作,Web Service體系必須為每一層標准技術提供Web Service協議棧。
在Web Service協議棧中,最為底層的是網絡傳輸層,Web服務協議是Web Service協議棧的基礎。用戶需要通過Web服務協議來調用服務接口。網絡傳輸層可以使用多種協議,包括HTTP、FTP以及SMTP。
在網絡傳輸層上一層的則是消息傳遞層,消息傳遞層使用SOAP(簡單對象訪問協議)作為消息傳遞協議,以實現服務提供者,服務注冊中心和服務請求者之間進行信息交換。
在消息傳底層之上的是服務描述層,服務描述層使用WSDL(Web Services Description Language)作為消息協議,WSDL使用XML語言來描述網絡服務,在前面的章節中也講到,WSDL具有自我描述性,它能夠提供Web服務的一些特定信息。服務描述層包括了WSDL文檔,這些文檔包括功能、接口、結構等定義和描述。
在服務描述層之上的是服務發布層,該層使用UDDI協議作為服務的發布/集成協議。UDDI提供了Web服務的注冊庫,用於存儲Web服務的描述信息。服務發布層能夠為提供者提供發布Web服務的功能,也能夠為服務請求者提供查詢,綁定的功能。
當Web Service中觸發了事件,如服務提供者發布服務接口、服務請求者請求服務等,服務提供者首先使用WSDL描述自己的服務接口,通過使用UDDI在服務器發布層向服務注冊中心發布服務接口。服務注冊中心則會返回WSDL文檔。當服務請求者對服務注冊中心執行服務請求,請求着通過WSDL文檔的描述綁定相應的服務接口。
4、簡單Web Service示例
在了解了Web Service基本的概念和協議棧的運行過程后,我們開始一個例子。
發布服務
新建一個項目(ASP.NET或MVC)作為Host。
1、添加一個“Web Service”文件(這個文件的后綴名是asmx)文件主要代碼如下:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
[WebMethod] //聲明為Web方法
public string HelloWorld()
{
return "Hello World";
}
}
2、修改、添加WebMethod方法
如:
[WebMethod]
public int Add(int a, int b)
{
return a + b;
}
[WebMethod]
public int Subtract(int a, int b)
{
return a - b;
}
3、運行。運行結果如下:
至此,一個簡單的WebService就發布完成了。
瀏覽器中看到的URL(類似於:http://localhost:8079/CalculatorService.asmx)就是我們的服務地址。
調用服務(消費者)
創建一個項目(ASP.NET、MVC、控制台、WinForm都行)作為Client。
1、添加一個服務引用,服務地址就是Host發布的那個地址(如果Host和Client在同一個解決方案下,我們也可以使用Discover來尋找服務地址),並為這個服務定義一個命名空間(比如CalculatorServiceRef)。
2、創建對應的SoapClient實例,調用其中的方法
如:
var client = new CalculatorServiceRef1.CalculatorServiceSoapClient();
Console.WriteLine(client.Add(1, 2));
這樣,對服務的調用就完成了。
5、有權限認證的Web Service
為了防止服務被隨意調用,我們需要對調用者進行身份認證。
可以使用SoapHeader實現權限認證。
1、創建SoapHeader
public class MySoapHeader : SoapHeader
{
public bool IsValidate()
{
......
}
}
2、修改WebService,使其支持SoapHeader
public class AuthService : System.Web.Services.WebService
{
//聲明Soap頭實例
public MySoapHeader myHeader = new MySoapHeader();
[SoapHeader("myHeader")]
[WebMethod]
public string HelloWorld()
{
myHeader.IsValidate();
return "嗨,終於有安全感了!";
}
}
這樣,有權限認證的Web Service就已完成。對這個服務的調用代碼將會發生改變:
var client = new AuthServiceRef.AuthServiceSoapClient();
var header = new AuthServiceRef.MySoapHeader { UserName = "admin", Password = "pwd" };
Console.WriteLine(client.Add(header, 3, 5));
WCF
1、了解WCF
Windows Communication Foundation(WCF)是由微軟開發的一系列支持數據通信的應用程序框架,可以翻譯為Windows 通訊開發平台。它整合了原有的windows通訊的 .net Remoting,WebService,Socket的機制,並融合有Http和Ftp的相關技術。是Windows平台上開發分布式應用最佳的實踐方式。
WCF框架模型如下:
WCF 提供了創建安全的、可靠的、事務服務的統一框架,WCF 整合和統一了現有分布式系統的開發技術,如 Enterprise Services、Messaging、Remoting、Web Services、WSE 等技術。
WCF對現有技術的封裝,使開發人員可以無需關心ASMX、.Net Remoting這些技術的實現細節。
WCF和其他分布式技術對比表
WCF遵循客戶端/服務器模型在應用程序之間進行通信,客戶端程序能夠通過服務器端提供的EndPoint端直接訪問服務,如下所示。
WCF中絕大部分的實現和功能都包含在一個單獨的程序集System.ServiceModel.dll中,命名空間為System.ServiceModel。通過使用System.ServiceModel命名空間能夠快速搭建WCF應用程序環境。
WCF中的服務可以是本地的,也可以使用遠程的服務。對於客戶端而言,客戶端只需要通過使用服務來實現應用程序功能,這些客戶端也可以是不同的類型,包括Windows應用程序,ASP.NET應用程序甚至是移動終端。
2、WCF的主要構成
Endpoint
Endpoint是WCF實現通信的核心要素。一個WCF Service由一個Endpoint集合組成,每個Endpoint就是用於通信的入口,客戶端和服務端通過Endpoint交換信息。
Endpoint由三部分組成:Address,Binding,Contract。為便於記憶,我們將這三部分稱為是WCF的ABC。
Address
Address通過一個URI唯一地標識一個Endpoint,並告訴潛在的調用者如何找到這個Endpoint。
Binding
Binding實現在Client和Service通信的所有底層細節。比如Client與Service之間傳遞的Message是如何編碼的—— text/XML, binary,MTOM;這種Message的傳遞是采用的哪種Transport——TCP, Http, Named Pipe, MSMQ; 以及采用怎樣的機制解決Secure Messaging的問題——SSL,Message Level Security。所以Binding解決的是How to communicate with service?
Contract
Contract的主要的作用是定義通信協議,具體Service提供了哪些方法。
Behavior
Behavior: Behavior的主要作用是定制Endpoint在運行時的一些必要的Behavior。比如服務元數據的發布設置,Service回調Client的Timeout;Client采用的Credential type;以及是否支持Transaction等。
WCF地址
在Internet中,為了標識每個計算機,就需要使用IP進行地址划分,同樣對於WCF服務而言,每個WCF服務都有一個自己的地址。
WCF地址包含兩個元素,服務位置與傳輸協議,服務位置包括目標機器名、站點或網絡、通信端口、管道或隊列,以及一個可選的特定路徑或者URI。傳輸協議包括:
HTTP:超文本傳輸協議。
TCP:傳輸控制協議。
Peer network:對等網。
IPC:基於命名管道的內部進程通信協議。
MSMQ:微軟消息隊列。
地址通常通過[基地址]/[可選的URI]的格式進行WCF地址描述,示例地址如下所示。
http://localhost:8731
http://localhost:8731/18-2
net.tcp://localhost:8731/server/18-2
net.pipe://localhost/18-2
net.msmq://localhost/18-2
3、契約
在WCF中,所有的WCF服務都會被公開成為契約。契約是服務的功能的標准描述方式,通常情況下WCF包含四種類型的契約。
示例如下。
[ServiceContract] //標識服務契約
public interface IService1 //服務接口
{
[OperationContract] //要發布的方法
string GetData(int value); //定義方法
}
服務契約(Service Contract):服務契約定包括兩種:ServiceContract和OperationContract
ServiceContract用於類或者結構上,用於指示WCF此類或者結構能夠被遠程調用,而OperationContract用於類中的方法(Method)上,用於指示WCF該方法可被遠程調用。
數據契約(Data Contract):數據契約定義了客戶端與服務器之間交互的數據類型。
錯誤契約(Fault Contract):錯誤契約定義了操作中出現的異常,包括定義服務出現的錯誤並傳遞返回給客戶端。
消息契約(Message Contract):消息契約能自定義消息格式,包括消息頭,消息體,還能指示是否對消息內容進行加密和簽名。
WCF服務如果需要復雜類型做參數,就必須對這個類型序列化。如果這個類型沒有標注為DataContract和DataMember的話,相當於標注了DataContract,並且默認所有public的屬性都要序列化。但是加的話,只有標注的屬性(或字段)才能序列化,而且即使那個屬性是私有的,一樣可以序列化,不受任何限制。
MessageContract和DataContract的區別:
使用MessageContract時,屬性要標注為MessageHeader或MessageBodyMember
使用DataContract時,屬性要標注為DataMember
如果Service和Client使用相同的契約(同為DataContract或MessageContract),那么客戶端的使用是比較簡單的,否則有點麻煩。具體見:http://www.cnblogs.com/Jax/archive/2010/05/08/1730807.html
4、WCF中支持的傳輸協議
包括HTTP、TCP、Peer network(對等網)、IPC(基於命名管道的內部進程通信)以及MSMQ(微軟消息隊列),每個協議對應一個地址類型:
1.TCP地址
TCP地址使用TCP傳輸控制協議作為通信協議,如:net.tcp://localhost:8731/server/18-2
如果端口號沒有指定,則TCP會使用默認端口號808作為其默認端口,如:net.tcp://localhost/server/18-2
2.HTTP地址
HTTP地址使用HTTP傳輸控制協議作為其通信協議,如:http://localhost:8731/18-2
如果端口號沒有指定,則HTTP會使用默認的端口號80作為其默認端口。
3.IPC和MSMQ地址
IPC地址使用net.pipe作為通信協議,如:net.pipe://localhost/18-2
(適用於跨進程,不能使用於不同機器間)
因為IPC地址使用net.pipe進行傳輸,所以IPC地址將使用Windows的命名管道機制。在WCF中,如果服務使用命名管道,則該服務只能接收來自同一台客戶端計算機的調用。因此,在使用時必須明確的指定WCF提供服務的計算機名,從而為管道名提供一個惟一的標識字符串。
而MSMQ地址使用net.msmq進行傳輸,即:使用了微軟消息隊列機制,如:net.msmq://localhost/18-2
5、WCF中提供的綁定有:
BasicHttpBinding: 最簡單的綁定類型,通常用於 Web Services。使用 HTTP 協議,Text/XML 編碼方式。
WSHttpBinding: 比 BasicHttpBinding 更加安全,通常用於 non-duplex 服務通訊。
WSDualHttpBinding: 和 WSHttpBinding 相比,它支持 duplex 類型的服務。
WSFederationHttpBinding: 支持 WS-Federation 安全通訊協議。
NetTcpBinding: 效率最高,安全的跨機器通訊方式。
NetNamedPipeBinding: 安全、可靠、高效的單機服務通訊方式。
NetMsmqBinding: 使用消息隊列在不同機器間進行通訊。
NetPeerTcpBinding: 使用 P2P 協議在多機器間通訊。
MsmqIntegrationBinding: 使用現有的消息隊列系統進行跨機器通訊。如 MSMQ。
6、WCF的宿主
WCF無法無法獨立運行,它必須寄宿在宿主程序上,WCF的宿主程序可以是Windows 服務、COM+應用程序、WAS(Windows Activation Services,Windows進程激活服務)或IIS、Windows應用程序,或簡單的控制台應用程序及任何.net程序。
IIS
1、使用WCF服務應用程序。
使用VS的“WCF服務應用程序”模板,VS自動幫我們生成了一個IService服務解決,並且通過Service.svc實現了它,配置文件也已寫好。
我們只需要修改IService以及 Service.svc就可以搞定WCF程序的開發。
並且,我們可以通過“WCF Test Client”對服務進行測試。方法是:鼠標點擊.svc文件,然后F5。
2、使用ASP.NET
在項目里新建一個“WCF Service”文件。剩下的事情與1類似。
3、使用ASP.NET MVC
與2類似。
控制台
在項目里新建一個“WCF Service”文件。VS自動幫我們生成了一個IService服務解決,並且通過Service.svc實現了它,配置文件也已寫好。
我們只需要修改IService以及 Service.svc。
然后在main函數中啟動服務,方法是:
var host = new ServiceHost(typeof(Service1));
host.Open();//打開宿主
也可以不使用“WCF Service”文件,自己手動創建一個接口文件及其實現類。這樣配置文件里面沒有任何關於WCF的配置,我們直接在main函數配置並且啟動服務。方法是:
Uri baseAddress = new Uri("http://localhost:12306/exam04.consolehost");
using (ServiceHost host = new ServiceHost(typeof(Exam04), baseAddress))
{
host.AddServiceEndpoint(typeof(IExam04), new BasicHttpBinding(), "");
//ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
//smb.HttpGetEnabled = true;
//host.Description.Behaviors.Add(smb);
host.Open();
Console.WriteLine("WCF中的HTTP監聽已啟動....");
Console.ReadLine();
host.Close();
}
Windows應用程序
和控制台類似。
當然了,我們可以通過一個事件來啟動WCF服務。
WAS
IIS7允許通過HTTP以外的協議進行激活和網絡通信。此環境適合開發可通過WCF支持的任何網絡協議(包括http、net.tcp、net.pipe、net.msmq)進行通信的WCF服務。部署簡單、管理方便,這些網絡協議在部署時可像Http一樣,直接丟到IIS7上即可。
的WCF Service由一個Endpoint集合組成,每個Endpoint就是用於通信的入口,客戶端和服務端通過Endpo
1、安裝IIS的WCF激活組件
安裝WCF的HTTP激活和非HTTP激活。
2、對網站添加net.tcp綁定
在網站的綁定里添加net.tcp,綁定信息中填寫“808.*”。
3、對網站(或虛擬目錄)開通net.tcp協議
網站(或虛擬目錄)的高級設置里,在“已啟用的協議”位置添加net.tcp,以逗號分隔。
4、建立服務程序
這一步和其它WCF服務的創建沒有不同。只是,我們要修改配置文件的協議:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="netTctBinding">
<security mode="None">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<services>
<service name="Example4.WASHost.Service1" behaviorConfiguration="myTcpBehavior">
<endpoint address="" binding ="netTcpBinding" contract="Example4.WASHost.IService1" bindingConfiguration="netTctBinding"/>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost/Example4.WASHost/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="myTcpBehavior">
<serviceMetadata httpGetEnabled="false" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
注意:設置了tcp協議后,在IIS Express里瀏覽服務,肯定會報:找不到具有綁定 NetTcpBinding 的終結點的與方案 net.tcp 匹配的基址。注冊的基址方案是 [http]。因為IIS Express沒有添加net.tcp綁定,也沒有開通net.tcp協議。
mex終結點綁定mexTcpBinding。並且behavior必須設置serviceMetadata,否則會顯示:在服務 Service1 實現的協定列表中找不到協定名稱 "IMetadataExchange"。而且需要將httpGetEnabled設置為false,否則只能打開http協議。
7、WCF服務的調用
在客戶端程序上添加服務引用,輸入服務的Address(如果宿主程序和客戶端在同一解決方案下,可以使用discover功能尋找服務)。
創建服務對應的Client類。如:var client = new ServiceReference1.StudentServiceClient();
調用。如:var list = client.GetAll();
8、WCF服務的通信模式
WCF在通信過程中有三種模式:請求應答、單向、雙工通信。
請求應答模式
之前的所有例子都是請求應答模式。
請求與答復模式為WCF的默認模式,即使返回值是void 也屬於請求與答復模式。
缺點:如果用服務的處理時間很長,客戶端要等待服務器處理完畢后才能繼續執行,因此響應能力將會大大下降。
優點:客戶端可以直接使用服務的返回值。
單工
客戶端向服務端發送求,但是不管服務端是否執行完成就接着執行下面的程序。
單向模式要在OpertaionContract的屬性中顯示設置值,代碼如下:
[OperationContract(IsOneWay = true)]
雙工 callback 服務端定義客戶端 創建上下端
雙工模式建立在上面兩種模式的基礎之上,實現客戶端與服務端相互的調用。相互調用:以往我們只是在客戶端調用服務端,然后服務端有返回值返回客戶端,而相互調用不光是客戶端調用服務端,而且服務端也可以調用客戶端的方法。
支持回調的綁定有4種:WSDualHttpBinding、NetTcpBinding、NetNamedPipeBinding、NetPeerTcpBinding。
因此服務端的binding要改為wsDualHttpBinding。
服務端:
[ServiceContract(CallbackContract = typeof(IService1Callback))]
public interface IService1
{
[OperationContract]
string ShowName(string name);
}
public interface IService1Callback
{
[OperationContract(IsOneWay = true)]
void PrintSomething(string str);
}
public class Service1 : IService1
{
IService1Callback callback = null;
public Service1()
{
callback=OperationContext.Current.GetCallbackChannel<IService1Callback>();
}
public string ShowName(string name)
{
......
callback.PrintSomething(“我完活了”);
return "搞定了" ;
}
}
客戶端:
首先要有一個callback類
public class CallbackHandler : ServiceReference1.IService1Callback
{
public void PrintSomething(string str)
{
Console.WriteLine(str);
}
}
調用服務
InstanceContext instanceContext = new InstanceContext(new CallbackHandler());
var client = new ServiceReference1.Service1Client(instanceContext);
Console.WriteLine(client.ShowName("ddd"));
9、Security
最簡單的就是通過MessageContract傳遞賬號密碼
10、不用svc文件
在config的serviceHostingEnvironment/serviceActivations下增加配置:
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" >
<serviceActivations>
<add factory="System.ServiceModel.Activation.ServiceHostFactory"
relativeAddress="./RequestResponse4/Service1.svc"
service="Host4.Service1" />
</serviceActivations>
</serviceHostingEnvironment>
也可以簡化為:
<add relativeAddress="RequestResponse4/Service1.svc" service="Host4.Service1" />
11、自定義地址路由映射(不用svc文件)
先在Global.asax中的Application_Start事件中添加以下代碼:
void Application_Start(object sender, EventArgs e)
{
System.Web.Routing.RouteTable.Routes.Add(
new System.ServiceModel.Activation.ServiceRoute("MyService",
new System.ServiceModel.Activation.WebServiceHostFactory(),
typeof(Service)));
}
其中"MyService"為自定義要在地址欄中映射的名稱
typeof(Service)中的"Service"為WCF中服務實現類Service.cs,一般繼承IService.cs接口
接下來修改web.config
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true">
然后再在Service.cs服務類上面添加:
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)] //記得引用using System.ServiceModel.Activation;
此外還有IService.cs接口的方法聲明中設置UriTemplate以接受參數:
[OperationContract, WebGet(UriTemplate = "{Name}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml)]
string GetName(string Name);
(webconfig不能配system.serviceModel的services)好像是變成REST了?
配置文件
服務端的配置文件主要是對services、bindings、behaviors的配置。
<services>配置節
<services>配置節中可以定義多個服務,每一個服務都被放到<service>配置節中,WCF的宿主程序可以通過配置文件找到這些定義的服務並發布這些服務。
<service>配置節包含name和behaviorConfiguration屬性。其中,name配置了實現Service Contract的類型名。類型名必須是完整地包含了命名空間和類型名。而behaviorConfiguration的配置值則與其后的<behaviors>配置節的內容有關。
<endpoint>是<service>配置節的主體,其中包含了endpoint的三個組成部分:A、B和C。
如果address值為空,那么endpoint的地址就是默認的基地址(Base Address)。這里所謂的基地址可以通過配置<host>來定義。
<identity> 節點下面,Certificate用於指定 X.509 證書的設置。此元素的類型為 CertificateElement。它包含一個 encodedValue 屬性,該屬性是一個字符串,用於指定此證書編碼的值。
dns 指定用於對服務進行身份驗證的 X.509 證書的 DNS。此元素包含一個字符串屬性 value,並包含實際的標識。
<behaviors>配置節
如果需要指定服務在執行方面的相關特性時,就必須定義服務的behavior。
例如通過指定ServiceMetadataBehavior,可以使WCF服務對外公布Metadata。
在WCF中,behavior被定義為Attribute,其中,ServiceBehavior和OperationBehavior是最常用的behavior。通過他們可以控制服務的如下屬性:
1、 對象實例的生命周期;
2、 並發與異步處理;
3、 配置行為;
4、 事務行為;
5、 序列化行為;
6、 元數據轉換;
7、 會話的生命周期;
8、 地址過濾以及消息頭的處理;
9、 模擬(Impersonation)。
也可以通過代碼的方式指定地址。如:
using (ServiceHost serviceHost = new ServiceHost(typeof (Service1)))
{
serviceHost.AddServiceEndpoint(typeof (IService1), new WSHttpBinding(),
"http://127.0.0.1:9999/Service1");
serviceHost.Open();
}
還可以通過“基地址+相對地址”的方式進行設置終結點地址。對於一個服務來說,可以指定一個或多個基地址,但是對於一種傳輸方式協議類型,只能具有一個唯一的基地址。
這也可以通過代碼實現:
Uri[] baseAddress =
{
new Uri("http://127.0.0.1:8888/myservices"),
new Uri("net.tcp://127.0.0.1/:8888")
};
using (ServiceHost serviceHost = new ServiceHost(typeof (Service1),baseAddress))
{
serviceHost.AddServiceEndpoint(
typeof (IService1),
new BasicHttpBinding(),
"Service1");
serviceHost.AddServiceEndpoint(
typeof (IService1),
new NetTcpBinding(),
"Service1");
serviceHost.Open();
}
<bindings>配置節
定義一個或多個系統提供的binding元素,例如<basicHttpBinding>
RBAC
權限管理包括兩部分工作:權限的設計,權限控制點。
A、權限的設計
通常采用RBAC(基於角色的訪問控制)方案。
通常會涉及:用戶表、權限表、角色表、用戶角色關系表、角色權限關系表5張表。有時還會涉及菜單表、頁面表、菜單權限關系表、菜單頁面關系表 等。
B、權限控制點
權限控制點是指:怎么防止非法訪問?如果只是基於菜單的權限控制,那么用戶可以直接通過URL地址訪問自己不該訪問的頁面。因此,需要一個全局的控制點,以保證所有的請求都會先經過控制點,然后進行身份驗證已決定這個訪問是否放行。
在ASP.NET里,我們可以將HttpHandler、HttpModule作為權限控制點。也可以通過重寫Page類實現權限控制。MVC里可以通過過濾器進行控制。
常見錯誤或技巧
WCF無法引入Model實體
客戶端無法調出service里需要的實體。這時候只需要在重新引用服務或者更新引用服務的時候,點“高級”按鈕,在服務引用設置對話框中,將“重新使用引用的程序集中的類型”這個勾取消,這樣就能安全的重新引用服務。
IncludeExceptionDetailInFaults
獲取或設置一個值,該值指示是否在錯誤中包含有關異常的詳細信息
httpGetEnabled
httpGetEnabled="true"表示允許用http的get方式獲取服務的元數據信息。如果用瀏覽器訪問時,得到一個“當前已禁用此服務的元數據發布”的提示,就是因為不允許以http的get方式獲取服務元數據造成的,這個屬性就是開啟此功能。
順便提一下,如果要生成客戶端代理的話,對http類型的binding,必須要開放get方式訪問元數據。
mex這個endpoint
這個endpoint比較特殊,它的binding是mexHttpBinding,服務契約是IMetadataExchange。這個endpoint是用於元數據發布的,它的功能實際上和剛才的httpGetEnabled="true"有些重復。
我們可以這樣理解,當開啟了httpGetEnabled時,用 http://...../DataService.svc?wsdl 就可以訪問到元數據;如果沒開啟,但有這個endpoint,用 http://...../DataService.svc/mex 也可以訪問到元數據;如果都沒有,那對不起,不允許你獲取元數據。(當然啦,如果你已經有契約了,不會影響調用的)
多加一句,對tcp類型的binding,有一個對應的mexTcpBinding用於獲取元數據,沒有定義它,svcutil.exe就不能生成tcp類binding的代理類。
沒有發布mex的服務,不能“go”,可以被discover但無法引用。但如果以前已經引用過,就可以繼續使用。
basicHttpBinding和wsHttpBinding
basicHttpBinding默認使用SOAP1.1.。
wsHttpBinding默認使用SOAP1.2(確切應該是Soap12WSAddressing10)
SOAP1.1有SOAPAction項,SOAP1.2沒有,當然SOAP1.2和1.1還有其他的區別,具有請查看w3的文檔
basicHttpBinding默認是使用soap1.1,但是basicHttpBinding是明文傳輸的,wsHttpBinding可以實現加密傳輸,但soap是soap1.2;可以利用自定義綁定(customBinding)設置soap版本為soap1.1,並且使用加密等傳輸方式:
runAllManagedModulesForAllRequests
在Global.ascx中,如想對每個Request都執行Application_BeginRequest,那么必須要在system.web或system.webServer中的modules中加入此屬性:
<modules runAllManagedModulesForAllRequests="true">
AspNetCompatibilityRequirementsAttribute
AspNetCompatibilityRequirementsAttribute 類用於 Windows Communication Foundation (WCF) 服務以指示該服務能否在 ASP.NET 兼容模式下運行。
在應用於服務實現類時,此屬性可指示該服務是否需要 ASP.NET 兼容模式,或是否支持為宿主應用程序域 (AppDomain) 啟用該兼容模式。
AppDomains 宿主 WCF 服務可在兩種不同的宿主模式下運行:
混合傳輸模式(默認):在這種模式下,WCF 服務不參與 ASP.NET HTTP 管線。 這可保證 WCF 服務行為的一致性,使其不受宿主環境和傳輸的影響。
ASP.NET 兼容模式:在這種模式下,WCF 服務以與 ASMX 服務類似的方式參與 ASP.NET HTTP 管線。ASP.NET 功能(例如,文件授權、URL 授權和 HTTP 會話狀態)適用於在此模式下運行的 WCF 服務。
宿主模式由應用程序級配置標志 aspNetCompatibilityEnabled 控制。
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
</system.serviceModel>
默認情況下,此標記為 false,因此,除非明確選擇使用 ASP.NET 兼容模式,否則 WCF 服務將在混合傳輸模式下運行。
有關以下內容的詳細信息ASP.NET 兼容模式,請參見 <serviceHostingEnvironment>。
使用 RequirementsMode 屬性可以實現此目的。 運行時,應用程序可以通過檢查靜態屬性AspNetCompatibilityEnabled 的值,來檢測是否啟用了 ASP.NET 兼容模式。
IIS 可以為每個站點指定多個綁定,這會導致每個方案有多個基址。 在 .NET Framework 3.5 之前,WCF 不支持一個方案有多個地址;如果指定了多個地址,則在激活期間引發 ArgumentException。
通過 .NET Framework 3.5,Internet 服務提供商可以在同一站點上使用同一方案的不同基址承載多個應用程序。
例如,一個站點可能包含以下基址:
http://payroll.myorg.com/Service.svc
http://shipping.myorg.com/Service.svc
從 .NET 4 開始,通過將 ServiceHostingEnvironment 的 MultipleSiteBindingsEnabled 設置為 True,您無需選取單個基址便可實現對 IIS 中多個綁定的支持。 此支持限於 HTTP 協議方案。
下面的配置代碼示例在 <serviceHostingEnvironment> 上使用 multipleSiteBindingsEnabled。
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled=”true” >
</serviceHostingEnvironment>
</system.serviceModel>
對svc文件改名
對svc文件改名后,如果不同時修改svc文件的Markup,
就會報:“找不到類型“XXX”,它在 ServiceHost 指令中提供為 Service 特性值,或在配置元素 system.serviceModel/serviceHostingEnvironment/serviceActivations 中提供。”
啟動WCF測試客戶端
當按F5的時候,焦點選定在特定服務的.svc或.xamlx文件時,就會啟動WCF測試客戶端。
元數據發布的2種方式:httpGetEnabled與mex
1、元數據即WSDL,描述了服務的細節,以便客戶端使用。
2、必須為服務配置ServiceMetadata行為,才能為其生成WSDL,才能再使用httpGetEnabled或mex將其公布出去
3、這兩種方式公布出去的WSDL無區別。但公布的方式有區別
此方式通過在服務在的URL后加“?wsdl”的方式公布WSDL,可直接通過HTTP訪問得到。
Behaviors節點
behaviors此元素定義名為 endpointBehaviors 和 serviceBehaviors 的兩個子集合。 每個集合分別定義終結點和服務所使用的行為元素。 每個行為元素由其唯一的 name 特性標識。 從 .NET Framework 4 開始,不要求綁定和行為具有名稱。 有關默認配置以及無名稱綁定和行為的更多信息,請參見簡化配置和 WCF 服務的簡化配置。
<!-- 為避免泄漏元數據信息,請在部署前將以下值設置為 false 並刪除上面的元數據終結點--> <serviceMetadata httpGetEnabled="true"/>
默認情況,WCF會把服務拋出的異常以FaultException類型傳遞到客戶端。使用FaultException<T>可以拋出更多細節,對T的唯一要求是必須標記為可序列化或數據契約。
服務里:throw new FaultException<MyFault>(new MyFault())
而OperationContract上加:[FaultContract(typeof(MyFault))]
baseAddresses
<endpoint address="ssss" binding="wsDualHttpBinding" contract="Host.IService1" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/Host/Service1/" />
</baseAddresses>
</host>
baseAddresses即基址。將來發布的服務地址是baseAddresses,mex地址是baseAddress/mex。
即:http://localhost:8733/Host/Service1/
但客戶端配置文件中的服務地址是服務端的baseAddresses+endpoint的address。
即:http://localhost:8733/Host/Service1/ssss
Mex終結點的address設置必須設置為相對地址
即:必須有baseAddresses,否則抱:ServiceMetadataBehavior的HttpGetEnabled屬性設置為true,而HttpGetUrl屬性是相對地址,但沒有http基址。
同時啟動多個WCF服務
Var conf = ConfigurationManager.OpenExeConfiguration(Assembly.GetCallingAssembly().Location);
Var svcmode = (ServiceModelSectionGroup)conf.GetSectionGroup("system.serviceModel");
ServiceHost host = null;
foreach (ServiceElement el in svcmode.Services.Services)
{
string serviceNameSpace = el.Name.Split('.')[0];
Type svcType = Type.GetType(el.Name + "," + serviceNameSpace);
if (svcType == null)
throw new Exception("Invalid Service Type " + el.Name + " in configuration file.");
host = new ServiceHost(svcType);
host.Opened += delegate
{ Console.WriteLine(el.Name + "服務已經啟動了"); };
host.Open();
}
服務端獲取客戶端IP
public string ClientIpAndPort()
{
OperationContext context = OperationContext.Current;
MessageProperties properties = context.IncomingMessageProperties;
RemoteEndpointMessageProperty endpoint =
properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
return endpoint.Address + "port" + endpoint.Port;
}
無法激活服務,因為它不支持 ASP.NET 兼容性
錯誤提示:無法激活服務,因為它不支持 ASP.NET 兼容性。已為此應用程序啟用了 ASP.NET 兼容性。請在 web.config 中關閉 ASP.NET 兼容性模式或將 AspNetCompatibilityRequirements 屬性添加到服務類型且同時將 RequirementsMode 設置為“Allowed”或“Required”。
默認情況下ASP.NET兼容性支持是關閉的,但很多時候需要打開Asp.Net的兼容性來利用Asp.Net的一些特性(使用session,上下文等),具體可參考http://msdn.microsoft.com/zh-cn/library/ms752234.aspx。
如果要打開兼容性,需要做兩步:
一是在服務類加上如下標記:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class AppRuntimeStateSvc : IAppRuntimeStateSvc
{
//服務代碼.
}
二是在web.config中的<system.serviceModel>段里加:
<serviceHostingEnvironment
multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
注意框架3.5以前都是默認就支持的,4.0以后默認就是沒有打開兼容性支持的.
REST
1、什么是REST
REST,即Representational State Transfer的縮寫。翻譯為"表現層狀態轉化"。
1、資源(Resources)
REST的"表現層"其實指的是"資源"(Resources)的"表現層"。因此URI就是每個資源的地址或識別符。
2、表現層(Representation)
"資源"是一種信息實體,它可以有多種外在表現形式。我們把"資源"具體呈現出來的形式,叫做它的"表現層"(Representation)。
URI只代表資源的實體,不代表它的形式。嚴格地說,有些網址最后的".html"后綴名是不必要的,因為這個后綴名表示格式,屬於"表現層"范疇,而URI應該只代表"資源"的位置。它的具體表現形式,應該在HTTP請求的頭信息中用Accept和Content-Type字段指定,這兩個字段才是對"表現層"的描述。
3、狀態轉化(State Transfer)
訪問一個網站,就代表了客戶端和服務器的一個互動過程。在這個過程中,勢必涉及到數據和狀態的變化。
互聯網通信協議HTTP協議,是一個無狀態協議。這意味着,所有的狀態都保存在服務器端。因此,如果客戶端想要操作服務器,必須通過某種手段,讓服務器端發生"狀態轉化"(State Transfer)。而這種轉化是建立在表現層之上的,所以就是"表現層狀態轉化"。
客戶端用到的手段,只能是HTTP協議。具體來說,就是HTTP協議里面,四個表示操作方式的動詞:GET、POST、PUT、DELETE。它們分別對應四種基本操作:GET用來獲取資源,POST用來新建資源(也可以用於更新資源),PUT用來更新資源,DELETE用來刪除資源。
綜述
綜合上面的解釋,我們總結一下什么是RESTful架構:
(1)每一個URI代表一種資源;
(2)客戶端和服務器之間,傳遞這種資源的某種表現層;
(3)客戶端通過四個HTTP動詞,對服務器端資源進行操作,實現"表現層狀態轉化"。
誤區
RESTful架構有一些典型的設計誤區。
最常見的一種設計錯誤,就是URI包含動詞。因為"資源"表示一種實體,所以應該是名詞,URI不應該有動詞,動詞應該放在HTTP協議中。
舉例來說,某個URI是/posts/show/1,其中show是動詞,這個URI就設計錯了,正確的寫法應該是/posts/1,然后用GET方法表示show。
如果某些動作是HTTP動詞表示不了的,你就應該把動作做成一種資源。比如網上匯款,從賬戶1向賬戶2匯款500元,錯誤的URI是:
POST /accounts/1/transfer/500/to/2
正確的寫法是把動詞transfer改成名詞transaction,資源不能是動詞,但是可以是一種服務:
POST /transaction HTTP/1.1
Host: 127.0.0.1
from=1&to=2&amount=500.00
另一個設計誤區,就是在URI中加入版本號:
http://www.example.com/app/1.0/foo
http://www.example.com/app/1.1/foo
http://www.example.com/app/2.0/foo
因為不同的版本,可以理解成同一種資源的不同表現形式,所以應該采用同一個URI。版本號可以在HTTP請求頭信息的Accept字段中進行區分
目前在三種主流的Web服務實現方案中,因為REST模式與復雜的SOAP和XML-RPC相比更加簡潔,越來越多的web服務開始采用REST風格設計和實現。
需要注意的是,REST是設計風格而不是標准。REST通常基於使用HTTP,URI,和XML以及HTML這些現有的廣泛流行的協議和標准。
資源是由URI來指定。
對資源的操作包括獲取、創建、修改和刪除資源,這些操作正好對應HTTP協議提供的GET、POST、PUT和DELETE方法。
通過操作資源的表現形式來操作資源。
資源的表現形式則是XML或者HTML,取決於讀者是機器還是人,是消費web服務的客戶軟件還是web瀏覽器。當然也可以是任何其他的格式。
下表列出了在實現 含狀態傳輸的 Web 服務時HTTP請求方法的典型用途。
HTTP 請求方法在RESTful Web 服務中的典型應用 |
||||
資源 |
GET |
PUT |
POST |
DELETE |
一組資源的URI,比如http://example.com/resources/ |
列出 URI,以及該資源組中每個資源的詳細信息(后者可選)。 |
使用給定的一組資源替換當前整組資源。 |
在本組資源中創建/追加一個新的資源。 該操作往往返回新資源的URL。 |
刪除整組資源。 |
單個資源的URI,比如http://example.com/resources/142 |
獲取 指定的資源的詳細信息,格式可以自選一個合適的網絡媒體類型(比如:XML、JSON等) |
替換/創建 指定的資源。並將其追加到相應的資源組中。 |
把指定的資源當做一個資源組,並在其下創建/追加一個新的元素,使其隸屬於當前資源。 |
刪除指定的元素。 |
使用WebInvoke和WebGet暴漏服務:
服務可以使用WebHttpBinding以及WebGet或者WebInvoke屬性來暴露。這些屬性每一個都確定HTTP動作、消息格式以及需要暴露給一個操作的消息體形式。
WebGet屬性使用GET動詞暴露操作。
[OperationContract]
[WebGet(UriTemplate ="/customer/{id}")]
public Customer GetCustomer(int id)
{
//Get customer from database
return customer;
}
[OperationContract]
[WebInvoke(Method="PUT", UriTemplate="/customer/{id}")]
public void PutCustomer(int id, Customer customer)
{
//Put customer in database
}
[OperationContract]
[WebInvoke(Method="Delete", UriTemplate="/customer/{id}")]
public void DeleteCustomer(int id)
{
//Put customer in database
}
URL和URI
區別就是URI定義資源,而URL不單定義這個資源,還定義了如何找到這個資源。
2、RESTful WCF
服務定義
WCF 中通過 WebGetAttribute、WebInvokeAttribute (GET/PUT/POST/DELETE)、UriTemplate 定義 REST 的服務的調用方式, 通過WebMessageFormat (Xml/Json) 定義消息傳遞的格式。
[WebGet(UriTemplate = "Tasks/Json", ResponseFormat = WebMessageFormat.Json)]
[WebInvoke(UriTemplate="Task/{title}", Method="GET", ResponseFormat=WebMessageFormat.Json)]
Svc發布
通過 WCF 4.0 里創建的 WCF Service Application 發布REST服務只需要在 svc 的 Markup 里加上:
<%@ Factory="System.ServiceModel.Activation.WebServiceHostFactory"%>
BTW: 不過這樣,WCF的Metadata就不能訪問到了,也就說不能訪問到svc的wsdl了。
通過瀏覽器訪問
OK,在瀏覽器中鍵入 http://localhost:2571/TaskService.svc/Tasks/Xml 就能得到結果:
通過c#代碼調用
客戶端的調用利用System.Net.WebClient:
var client = new WebClient();
this.txtResponse.Text = client.DownloadString(url);
通過js調用
<script type="text/javascript">
$(document).ready(function () {
$("#btnGet").click(function () {
var url = $("#txtUrl").val();
$.get(url, function (data) {
for (var i = 0; i < data.length; i++)
$("#divResponse").append("<li>" +
data[i].Title + " - " +
data[i].Detail + "</li>");
});
});
});
</script>
使用Put、Delete、Post
可以使用WebClient
using (var client = new WebClient())
{
client.UploadString(url, "DELETE", "");
}
或者WebRequest
var request = WebRequest.Create(url);
request.Method = "DELETE";
var response = (HttpWebResponse)request.GetResponse();
但是WebClient不支持PUT和DELETE!(所以就簡單使用GET、POST吧)
因為REST 是基於HTTP的, 所以對於 REST 的客戶端的開發者,無法像傳統的 WebService或者其他的WCF服務通過引用wsdl,享受“奢侈”的代碼生成,而使用強類型的本地代理調用服務。 開發者只能通過 Http Request 的組裝, 但正因為這種直接的HttpRequest組裝,而使得客戶端真正是語言無關的。這里不得不提一下 Microsoft.Http.dll 和 Microsoft.Http.Extensions.dll,它們是微軟提供的REST客戶端包。可以更加方便地操作 HttpRequest/Response,
但是:
The WCF REST Starter Kit is no longer supported. For building RESTful services on .NET please use *ASP.NET Web API.
Basic Security
在SOAP協議的WCF中,可以通過SOAPHeader(MessageHeader)來實現用戶名密碼的傳輸。在REST WCF中,可以利用 HttpHeader。
服務器端驗證客戶端傳來的Header:
var ctx = WebOperationContext.Current;
var auth = ctx.IncomingRequest.Headers["a"];
if (string.IsNullOrEmpty(auth) || auth != "b")
{
ctx.OutgoingResponse.StatusCode = HttpStatusCode.MethodNotAllowed;
throw new Exception("賬號密碼錯誤");
}
客戶端發送Header:
var request = WebRequest.Create(url);
request.ContentType = "application/json";
request.Method = "GET";
request.Headers.Add("a", "c");
var response = (HttpWebResponse)request.GetResponse();
全局控制Security
public class MySecureWebServiceHostFactory : WebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var host = base.CreateServiceHost(serviceType, baseAddresses);
host.Authorization.ServiceAuthorizationManager = new MyServiceAuthorizationManager();
return host;
}
public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
{
var host = base.CreateServiceHost(constructorString, baseAddresses);
host.Authorization.ServiceAuthorizationManager = new MyServiceAuthorizationManager();
return host;
}
}
public class MyServiceAuthorizationManager : ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
var ctx = WebOperationContext.Current;
var auth = ctx.IncomingRequest.Headers["a"];
if (string.IsNullOrEmpty(auth) || auth != "123")
{
ctx.OutgoingResponse.StatusCode = HttpStatusCode.MethodNotAllowed;
return false;
}
return true;
}
}
在Global中配置:
var securewebServiceHostFactory = new MySecureWebServiceHostFactory();
RouteTable.Routes.Add(new ServiceRoute("Task2Service",
securewebServiceHostFactory, typeof(Task2Service)));
3、直接在Web Application里發布RESTful WCF
服務定義
添加引用
System.Runtime.Serialization、
System.ServiceModel、
System.ServiceModel.Web、
System.ServiceModel.Activation
直接定義契約和其實現。
注冊服務路由
在Globel.asax中的Application_Start事件中注冊服務。並且注冊的"XService"自動成為服務的基地址,即 http://<machine_name>:<port>/XService/
RouteTable.Routes.Add(new ServiceRoute("TaskService",
new WebServiceHostFactory(), typeof(TaskService)));
ASP.NET 路由集成功能要求 ASP.NET 兼容性
如果要與ASP.NET 並行承載 WCF 服務,並在 ASP.NET 兼容模式中承載它們。需要設置ASP.NET兼容性。
盡管 WCF 模型旨在跨宿主環境和傳輸保持行為的一致性,但經常在一些方案中,應用程序中不要求這種程度的靈活性。 WCF 的 ASP.NET 兼容模式適用於具有以下特點的方案:不需要具有在 IIS 外部承載或通過 HTTP 之外的協議進行通信的能力,但使用 ASP.NET Web 應用程序平台的所有功能。
在默認的並行配置中,承載基礎結構的 WCF 截獲 WCF 消息並將其路由到 HTTP 管道之外;與此不同的是,在 ASP.NET 兼容模式中運行的 WCF 服務完全參與 ASP.NET HTTP 請求生命周期。 在兼容模式中,WCF 服務通過 IHttpHandler 實現來使用 HTTP 管道,其方式類似於處理 ASPX 頁和 ASMX Web 服務的請求。 因此,WCF 的行為在以下 ASP.NET 功能方面與 ASMX 相同:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
Web API
1、了解WCF
Windows Communication Foundation(WCF)是由微軟開發的一系列支持數據通信的應用程序框架,可以翻譯為Windows 通訊開發平台。它整合了原有的windows通訊的 .net Remoting,WebService,Socket的機制,並融合有Http和Ftp的相關技術。是Windows平台上開發分布式應用最佳的實踐方式。
WCF框架模型如下: