WCF 之 消息契约(MessageContract)
對(duì)于SOAP來說主要由兩部分構(gòu)成Header和Body,他們兩個(gè)共同構(gòu)成了SOAP的信封,通常來說Body保存具體的數(shù)據(jù)內(nèi)容,Header保存一些上下文信息或關(guān)鍵信息。
比如:在一些情況下,具有這樣的要求:當(dāng)序列化一個(gè)對(duì)象并生成消息的時(shí)候,希望將部分?jǐn)?shù)據(jù)成員作為SOAP的報(bào)頭,部分作為消息的主體。比如說,我們有一個(gè)服務(wù)操作采用流的方式進(jìn)行文件的上載,除了以流的方式傳輸以二進(jìn)制表示的文件內(nèi)容外,還需要傳輸一個(gè)額外的基于文件屬性的信息,比如文件格式、文件大小等。一般的做法是將傳輸文件內(nèi)容的流作為SOAP的主體,將其屬性內(nèi)容作為SOAP的報(bào)頭進(jìn)行傳遞。這樣的功能,可以通過定義消息契約來實(shí)現(xiàn)。
由此可見,MessageContract的主要作用就是給我們提供了自己來操作SOAP的一種方式。
MessageContractAttribute:對(duì)控制消息頭和消息體元素提供了強(qiáng)力支持。
所支持的屬性:?MessageHeaderAttribute 和 MessageBodyMemberAttribute。
用于及用途:
[1] 添加自定義頭(custom headers);
[2] 控制消息是否被包裝;
[3] 控制簽名與加密;
一、[MessageContract]:
[1] 將一個(gè)類型轉(zhuǎn)換為SOAP消息
類型可以包含消息頭和消息體的元素
[2] 能夠設(shè)置IsWrapped, ProtectionLevel
[3] 可以設(shè)置顯式Name, Namespace
如下面的代碼:
[MessageContract(IsWrapped=true, ProtectionLevel=ProtectionLevel.Sign)] public class SaveLinkRequest {…} [MessageContract] public class SaveLinkResponse {…}?
二、[MessageHeader]:
1 應(yīng)用到消息契約的域(fields)或者(properties)
為創(chuàng)建自定義頭提供了簡單的方法
2 能夠提供Name, Namespace, ProtectionLevel
3 可以設(shè)置SOAP協(xié)議的設(shè)置:Relay, Actor,MustUnderstand
三、[MessageBody]:
[1] 應(yīng)用到消息契約的域(fields)或者屬性(properties)
[2] 能夠擁有多個(gè)body元素
– 等價(jià)于在操作中擁有多個(gè)參數(shù)
– 返回多個(gè)復(fù)雜類型數(shù)據(jù)的唯一方法
? 總是提供順序(Order)
? 可以設(shè)置Name, Namespace, ProtectionLevel
?
?
那么如何應(yīng)用消息契約那?不要急,下面來介紹,還是來看代碼吧:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.Serialization;namespace ContentTypes {[DataContract]public class LinkItem{private long m_id;private string m_title;private string m_description;private DateTime m_dateStart;private DateTime m_dateEnd;private string m_url;[DataMember]public long Id{get { return m_id; }set { m_id = value; }}[DataMember]public string Title{get { return m_title; }set { m_title = value; }}[DataMember]public string Description{get { return m_description; }set { m_description = value; }}[DataMember]public DateTime DateStart{get { return m_dateStart; }set { m_dateStart = value; }}[DataMember]public DateTime DateEnd{get { return m_dateEnd; }set { m_dateEnd = value; }}[DataMember]public string Url{get { return m_url; }set { m_url = value; }}} } LinkItem重點(diǎn)看Message和Service代碼:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using ContentTypes;namespace WcfServiceLibraryDemo {[MessageContract(IsWrapped = false)]public class SaveGigRequest{private LinkItem m_linkItem;[MessageBodyMember]public LinkItem Item{get { return m_linkItem; }set { m_linkItem = value; }}}[MessageContract(IsWrapped = false)]public class SaveGigResponse{}[MessageContract(IsWrapped = false)]public class GetGigRequest{private string m_licenseKey;[MessageHeader]public string LicenseKey{get { return m_licenseKey; }set { m_licenseKey = value; }}}[MessageContract(IsWrapped = false)]public class GetGigResponse{private LinkItem m_linkItem;public GetGigResponse(){}public GetGigResponse(LinkItem item){this.m_linkItem = item;}[MessageBodyMember]public LinkItem Item{get { return m_linkItem; }set { m_linkItem = value; }}} } Message只要記住一條就行了,凡是有[MessageHeader]或[MessageBody]的那些屬性,它們就是在客戶端調(diào)用服務(wù)相應(yīng)方法的參數(shù)。
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using ContentTypes;namespace WcfServiceLibraryDemo {[ServiceContract(Name = "GigManagerServiceContract", Namespace = "http://www.cnblogs.com/Charlesliu", SessionMode = SessionMode.Required)]public interface IGigManagerService{[OperationContract]SaveGigResponse SaveGig(SaveGigRequest requestMessage);[OperationContract]GetGigResponse GetGig(GetGigRequest requestMessage);} } IService using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using ContentTypes;namespace WcfServiceLibraryDemo {[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]public class GigManagerService : IGigManagerService{private LinkItem m_linkItem;#region IGigManager Memberspublic SaveGigResponse SaveGig(SaveGigRequest requestMessage){m_linkItem = requestMessage.Item;return new SaveGigResponse();}public GetGigResponse GetGig(GetGigRequest requestMessage){if (requestMessage.LicenseKey != "XXX")throw new FaultException("Invalid license key.");return new GetGigResponse(m_linkItem);}#endregion} } Service客戶端代碼:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using WinTest.MyServiceReference;namespace WinTest {public partial class Form1 : Form{MyServiceReference.GigManagerServiceContractClient m_proxy = new WinTest.MyServiceReference.GigManagerServiceContractClient();public Form1(){InitializeComponent();}private void cmdSave_Click(object sender, EventArgs e){LinkItem item = new LinkItem();item.Id = int.Parse(this.txtId.Text);item.Title = this.txtTitle.Text;item.Description = this.txtDescription.Text;item.DateStart = this.dtpStart.Value;item.DateEnd = this.dtpEnd.Value;item.Url = this.txtUrl.Text;m_proxy.SaveGig(item);}private void cmdGet_Click(object sender, EventArgs e){LinkItem item = m_proxy.GetGig("XXX");if (item != null){this.txtId.Text = item.Id.ToString();this.txtTitle.Text = item.Title;this.txtDescription.Text = item.Description;if (item.DateStart != DateTime.MinValue)this.dtpStart.Value = item.DateStart;if (item.DateEnd != DateTime.MinValue)this.dtpEnd.Value = (DateTime)item.DateEnd;this.txtUrl.Text = item.Url;}}} } 客戶端IsWrapped、WrapperName、WrapperNamespace:IsWrapped表述的含義是是否為定義的主體成員(一個(gè)或者多個(gè))添加一個(gè)額外的根節(jié)點(diǎn)。WrapperName和WrapperNamespace則表述該根節(jié)點(diǎn)的名稱和命名空間。IsWrapped、WrapperName、WrapperNamespace的默認(rèn)是分別為true、類型名稱和http://tempuri.org/。如果我們將IsWrapped的屬性設(shè)為false,那么套在Address節(jié)點(diǎn)外的Customer節(jié)點(diǎn)將會(huì)從SOAP消息中去除。
我們?cè)谑褂弥邪l(fā)現(xiàn)一個(gè)特點(diǎn),用這種方式序列化的實(shí)體類不能當(dāng)作參數(shù)直接傳遞,客戶端會(huì)把對(duì)象的一個(gè)參數(shù)拆分為多個(gè)屬性作為參數(shù)。
總結(jié)
以上是生活随笔為你收集整理的WCF 之 消息契约(MessageContract)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bzoj1597[Usaco2008 M
- 下一篇: gcc-5.4.0 static dwa