WCF 之 消息契约(MessageContract)
对于SOAP来说主要由两部分构成Header和Body,他们两个共同构成了SOAP的信封,通常来说Body保存具体的数据内容,Header保存一些上下文信息或关键信息。
比如:在一些情况下,具有这样的要求:当序列化一个对象并生成消息的时候,希望将部分数据成员作为SOAP的报头,部分作为消息的主体。比如说,我们有一个服务操作采用流的方式进行文件的上载,除了以流的方式传输以二进制表示的文件内容外,还需要传输一个额外的基于文件属性的信息,比如文件格式、文件大小等。一般的做法是将传输文件内容的流作为SOAP的主体,将其属性内容作为SOAP的报头进行传递。这样的功能,可以通过定义消息契约来实现。
由此可见,MessageContract的主要作用就是给我们提供了自己来操作SOAP的一种方式。
MessageContractAttribute:对控制消息头和消息体元素提供了强力支持。
所支持的属性: MessageHeaderAttribute 和 MessageBodyMemberAttribute。
用于及用途:
[1] 添加自定义头(custom headers);
[2] 控制消息是否被包装;
[3] 控制签名与加密;
一、[MessageContract]:
[1] 将一个类型转换为SOAP消息
类型可以包含消息头和消息体的元素
[2] 能够设置IsWrapped, ProtectionLevel
[3] 可以设置显式Name, Namespace
如下面的代码:
[MessageContract(IsWrapped=true, ProtectionLevel=ProtectionLevel.Sign)]
public class SaveLinkRequest
{…}
[MessageContract]
public class SaveLinkResponse
{…}
二、[MessageHeader]:
1 应用到消息契约的域(fields)或者(properties)
为创建自定义头提供了简单的方法
2 能够提供Name, Namespace, ProtectionLevel
3 可以设置SOAP协议的设置:Relay, Actor,MustUnderstand
三、[MessageBody]:
[1] 应用到消息契约的域(fields)或者属性(properties)
[2] 能够拥有多个body元素
– 等价于在操作中拥有多个参数
– 返回多个复杂类型数据的唯一方法
• 总是提供顺序(Order)
• 可以设置Name, Namespace, ProtectionLevel
[MessageContract(IsWrapped = true, ProtectionLevel = ProtectionLevel.Sign)]
public class SaveEventRequest
{
private string m_licenseKey;
private LinkItem m_linkItem;
[MessageHeader(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
public string LicenseKey
{
get { return m_licenseKey; }
set { m_licenseKey = value; }
}
[MessageBodyMember]
public LinkItem LinkItem
{
get { return m_linkItem; }
set { m_linkItem = value; }
}
}
[MessageContract]
public class SaveEventResponse
{
}
那么如何应用消息契约那?不要急,下面来介绍,还是来看代码吧:

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
重点看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]的那些属性,它们就是在客户端调用服务相应方法的参数。
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 Members public 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表述的含义是是否为定义的主体成员(一个或者多个)添加一个额外的根节点。WrapperName和WrapperNamespace则表述该根节点的名称和命名空间。IsWrapped、WrapperName、WrapperNamespace的默认是分别为true、类型名称和http://tempuri.org/。如果我们将IsWrapped的属性设为false,那么套在Address节点外的Customer节点将会从SOAP消息中去除。
我们在使用中发现一个特点,用这种方式序列化的实体类不能当作参数直接传递,客户端会把对象的一个参数拆分为多个属性作为参数。
WCF 之 消息契约(MessageContract)的更多相关文章
- 重温WCF之消息契约(MessageContract)(六)
对于SOAP来说主要由两部分构成Header和Body,他们两个共同构成了SOAP的信封,通常来说Body保存具体的数据内容,Header保存一些上下文信息或关键信息.比如:在一些情况下,具有这样的要 ...
- C# 的 WCF文章 消息契约(Message Contract)在流(Stream )传输大文件中的应用
我也遇到同样问题,所以抄下做MARK http://www.cnblogs.com/lmjq/archive/2011/07/19/2110319.html 刚做完一个binding为netTcpBi ...
- WCF契约之---服务契约 、数据契约、 消息契约
本篇博文只是简单说下WCF中的契约的种类.作用以及一些简单的代码示例.在WCF中契约分为服务契约.数据契约和消息契约.下面对这几种契约进行简单的介绍. 服务契约 服务契约描述了暴露给外部的类型(接口或 ...
- WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化
原文:WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化 [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制 ...
- WCF把书读薄(3)——数据契约、消息契约与错误契约
上一篇:WCF把书读薄(2)——消息交换.服务实例.会话与并发 十二.数据契约 在实际应用当中数据不可能仅仅是以int Add(int num1, int num2)这种简单的几个int的方式进行传输 ...
- wcf消息契约
1.最多一个参数和一个返回值,返回值和参数的类型都是消息类型. 下面的代码为定义一个消息契约的实例 [MessageContract] public class MyMessage { ...
- [WCF编程]4.契约概述
一.契约的基本概念 契约是消息参与者之间的约定.在SOA架构中,契约提供了服务通信所必需的元数据.契约用来定义数据类型,操作,消息交换模式和消息交换使用的传输协议.契约通常是在标准化平台中使用与编程语 ...
- WCF中DataContract和MessageContract的区别
一.代码案例 首选建立2个WCF Service,它们分别使用不同的Contract,同时创建一个Console控制台项目,作为Client: 其中,WcfServiceWithDataContrac ...
- 【原创经验分享】WCF之消息队列
最近都在鼓捣这个WCF,因为看到说WCF比WebService功能要强大许多,另外也看了一些公司的招聘信息,貌似一些中.高级的程序员招聘,都有提及到WCF这一块,所以,自己也关心关心一下,虽然目前工作 ...
随机推荐
- 2017/11/6 Leetcode 日记
2017/11/6 Leetcode 日记 344. Reverse String Write a function that takes a string as input and returns ...
- 【BZOJ 2510】 2510: 弱题 (矩阵乘法、循环矩阵的矩阵乘法)
2510: 弱题 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 374 Solved: 196 Description 有M个球,一开始每个球均有一 ...
- 【BZOJ 3229】 3229: [Sdoi2008]石子合并 (GarsiaWachs算法)
3229: [Sdoi2008]石子合并 Description 在一个操场上摆放着一排N堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合 ...
- 51nod1624 取余最长路 前缀和 + set
由于只有3行,因此只会会换行2次,假设$x, y$分别为这两次的换行点 那么答案为$S[1][x] +S[2][y] - S[2][x - 1] + S[3][n] - S[3][y - 1]$ 其中 ...
- 莫队p2 【bzoj3809】Gty的二逼妹子序列
发现一篇已经够长了...所以就放在这里吧... http://hzwer.com/5749.html ↑依然是看大牛题解过的 袜子那道题太简单了.... 然后被这道题超时卡了一段时间....... ...
- 【最小割】【Dinic】HihoCoder - 1252 - The 2015 ACM-ICPC Asia Beijing Regional Contest - D - Kejin Game
题意:有一个技能学习表,是一个DAG,要想正常学习到技能x,要将指向x的技能全部先学到,然后会有一个正常花费cx.然后你还有一种方案,通过氪金dx直接获得技能x.你还可以通过一定的代价,切断一条边.问 ...
- web.xml2.3配置需要注意的顺序问题
今天在做一个街道办事处项目时,用了eWebeditor编辑器,在按照说明文件进行web.xml配置时,在<web-app>一行上出现红叉,提示信息为:The content of elem ...
- jsp和servlet有哪些相同点和不同点,它们之间的联系是什么?
1.jsp经编译后就变成了servlet(jsp本质就是servlet,jvm只能识别java的类,不能识别jsp代码,web容器将jsp的代码编译成jvm能够识别的java类) 2.jsp更擅长表现 ...
- C++继承引入的隐藏与重写
在区分隐藏和重写之前,先来理一理关于继承的东西... [继承] 继承是面向对象复用的重要手段,是类型之间的关系建模.通过继承一个类,共享公有的东西,实现各自本质不同的东西.简单的说,继承就是指一个对象 ...
- python - 在Windows系统中安装Pygame及导入Eclipse
环境:python3.6(只有一个版本)+ windows10(64 bit) + Eclipse+pydev python3.6安装完成后,会自带 easy_install 和 pip3,在Win ...