文章目錄
本篇博文只是簡單說下WCF中的契約的種類、作用以及一些簡單的程式碼範例。在WCF中契約分為服務契約、資料契約和訊息契約。下面對這幾種契約進行簡單的介紹。
服務契約
服務契約描述了暴露給外部的類型(介面或類)、服務所支援的操作、使用的訊息交換模式和訊息的格式。每個WCF服務必須實現至少一個服務契約。使用服務契約必須要引用命名空間System.ServiceModel 。服務契約中常用到的三個特性:
ServiceContractAttribute
該特性定義在類或介面上,用來描述一個相關操作的集合。ServiceContractAttribute特性還有如下的一些屬性值可以設定:
Name:給服務契約定義一個名稱,而不是使用介面或是類的類型名,在用戶端加入服務參考時會用到。
Namespace:命名空間,預設值為http://tempuri.org。
CallbackContract:將另一個服務契約定義為回調契約,使得用戶端可以接收服務端的非同步訊息。
ProtectionLevel:控制契約中發送給訊息的保護方式是否需要被簽名和加密。該屬性為System.Net.Security.ProtectionLevel枚舉類型。
SessionMode:確定會話是否為公開服務契約的端點所支援。
ConfigurationName:服務的配置名稱。
[ServiceContract(Name="HelloWorld",Namespace="http://oec2003.cnblogs.com"]public interface IHelloWorldService{ }OperationContractAttribute
用OperationContractAttribute標記的方法即為一個服務作業,簡單的使用該特性就可以讓一個方法加入到服務契約的操作隊列中,可以被用戶端所調用。該特性也有一些設定訊息交換方式的屬性。如下
Name:定義一個操作名稱,而不是使用方法名稱。
Action:該操作訊息的動作標題。
ReplyAction:響應該操作訊息的動作標題。
IsOneWay:設定該操作是否單向和沒有回複,如果操作是單向的,將不支援ReplyAction。
ProtectionLevel:允許你控制特定的操作訊息是否被保護,操作中的ProtectionLevel屬性將覆蓋服務契約中的ProtectionLevel。該屬性為System.Net.Security.ProtectionLevel枚舉類型。
IsInitiating:操作是否可以用來初始化會話。
IsTerminating:操作是否中止一個會話。
AsyncPattern:將服務作業定義為非同步實現模式。
[ServiceContract(Namespace="http://oec2003.cnblogs.com",Name="oec2003", ConfigurationName="IHelloWorldService")]public interface IHelloWorldService{ [OperationContract(Name="oec2003SayHello", Action = "http://oec2003.cnblogs.com/IHelloWorldService/Hello", ReplyAction = "http://oec2003.cnblogs.com/IHelloWorldService/HelloReply")] string SayHello();}MessageParameterAttribute
使用 MessageParameterAttribute 可以控制參數或傳回值的名稱。此屬性對於已用 MessageContractAttribute 特性標記的參數無效。該特性只有一個Name屬性,看如下代碼:
[ServiceContract(Namespace="http://oec2003.cnblogs.com",Name="oec2003", ConfigurationName="IHelloWorldService")]public interface IHelloWorldService{ [OperationContract] [return: MessageParameter(Name = "responseString")] string SayHello([MessageParameter(Name = "string")]string meg);}
資料契約
使用資料契約必須引用System.Runtime.Serialization命名空間,在類型上使用DataContractAttribute可以建立資料契約,類型中的成員使用DataMember標記。代碼如下:
[DataContract]public class User{ [DataMember] public int Age { get; set; } [DataMember] public string Name { get; set; } [DataMember] public string Email { get; set; }}DataContractAttribute
DataContractAttribute特性定義在類型之上,類型包括類、結構、枚舉但不包括介面。DataContractAttribute特性不能被繼承,即繼承自有DataContractAttribute特性標記的類並不是資料契約,必須顯示使用DataContractAttribute標記才能成為資料契約。DataContractAttribute特性有IsReference、Name和Namespace三個屬性:
IsReference:bool類型,表示在進行序列化的時候是否保持對象現有的引用結構。
Name:名稱。
Namespace:命名空間。
[DataContract(IsReference=true,Name="MyUser",Namespace="http://oec2003.cnblogs.com")]public class User{ [DataMember] public int Age { get; set; } [DataMember] public string Name { get; set; } [DataMember] public string Email { get; set; }}DataMemberAttribute
使用DataMemberAttribute標記的類型成員才能成為資料契約的資料成員。這個和服務契約中的OperationContractAttribute類似。DataMemberAttribute特性有如下四個屬性:
EmitDefaultValue:表明在資料成員的值等於預設值的情況下,是否還須要將其序列化到最終的XML中,預設值為true,表示預設值會參與序列化。
IsRequired:bool類型,表明屬性成員是否是必須的成員,預設值為false。
Name:資料成員的別名。
Order:相應的資料成員在最終序列化的XML中出現的位置,預設是按字母順序排列的。
[DataContract(IsReference=true,Name="MyUser",Namespace="http://oec2003.cnblogs.com")]public class User{ [DataMember(EmitDefaultValue=true,IsRequired=true, Name="Oec2003_Age",Order=1)] public int Age { get; set; } [DataMember(EmitDefaultValue = true, IsRequired = true, Name = "Oec2003_Name", Order = 2)] public string Name { get; set; } [DataMember(EmitDefaultValue = true, IsRequired = false, Name = "Oec2003_Email", Order = 3)] public string Email { get; set; }
訊息契約
使用訊息契約必須引用System.ServiceModel命名空間,訊息契約和資料契約一樣都是定義在資料類型上。和資料契約不同的是訊息契約更多的是關注資料成員在SOAP訊息中的表示。定義一個訊息契約需要用到MessageContractAttribute特性,另外還涉及到MessageHeaderAttribute和MessageBodyMemberAttribute這兩個特性,MessageContractAttribute特性標記在類型上,MessageHeaderAttribute和MessageBodyMemberAttribute特性標記在資料成員上。
[MessageContract]public class MessageTest{ [MessageHeader] public int Age { get; set; } [MessageHeader] public string Name { get; set; } [MessageBodyMember] public string Email { get; set; }}MessageContractAttribute
通過在一個類型上使用MessageContractAttribute標記可以使之成為一個訊息契約。MessageContractAttribute特性含有如下幾個屬性:
IsWrapped:是否為定義的主體成員(一個或者多個)添加一個額外的根節點。
WrapperName:根節點的名稱。
WrapperNamespace:根節點的命名空間。
ProtectionLevel:表示保護層級,WCF中通過System.Net.Security.ProtectionLevel枚舉定義訊息的保護層級。一般有3種可選的保護層級:None、Sign和EncryptAndSign。
[MessageContract(IsWrapped=false,WrapperName="MyMessage", WrapperNamespace="http://oec2003.com")]public class MessageTest{ //省略}MessageHeaderAttribute
使用MessageHeaderAttribute標記的資料成員將會出現在SOAP訊息的頭部,該特性包含下面幾個屬性:
Actor:為一個URI值,表示處理該前序的目標節點。
MustUnderstand:bool類型,表明Actor定義的節點是否必須理解並處理該節點。
Name:名稱。
Namespace:命名空間。
ProtectionLevel:表示保護層級。
Relay:表明該前序是否需要傳遞到下一個SOAP節點。
[MessageContract]public class MessageTest{ [MessageHeader(Actor="http://oec2003.com/Age",MustUnderstand=true,Name="MyAge", Namespace="http://oec2003.com",Relay=true)] public int Age { get; set; } [MessageHeader] public string Name { get; set; }}MessageBodyMemberAttribute
使用MessageHeaderAttribute標記的資料成員將會出現在SOAP訊息的主體部分,該特性包含下面的屬性:
Order:Order屬性用來控製成員在SOAP主體部分中出現的位置,預設按字母順序排列。
Name:名稱。
Namespace:命名空間。
ProtectionLevel:表示保護層級。
[MessageContract(IsWrapped=false,WrapperName="MyMessage", WrapperNamespace="http://oec2003.com")]public class MessageTest{ [MessageBodyMember(Order = 1)] public string Email { get; set; }}