WSE是什么?
它是Web Service Enhancements,是微软发布的构筑Web服务应用程序的附加套件。这个套件可以使web服务应用程序支持WS-Security、WS-Routing、WS-Attachments等规格。
(1)安全性:支援对平台安全的xml web服务的构筑,具有用于对soap信息进行电子签名和加密的功能。
(2)路由功能,对soap信息进行中继,并负责xml web服务的路由
(3)添加功能,可以向xml web服务soap信息中添加二进制数据。
在.net Web服务中,不支持MIME格式的soap附件,但在WSE2.0中却支持DIME附件,现在的WSE版本为3.0,在2.0中的DIME附件,在3.0中由MTOM模型代替。
关于wse更多内容可以参见老徐的系列:
http://www.cnblogs.com/frank_xl/admin/EditPosts.aspx?catid=177055
现在通过WSE3.0构建附件Soap消息包。
(一) WSE服务端
WSE3.0可以到:
http://www.microsoft.com/downloads/details.aspx?
familyid=
下载
支持vs2005,其它版本的支持请参考其它文档。安装时以插件形式安装。
建立网站,并添加web 服务:
[WebMethod]
public void SaveImage(byte[] bb)
{
FileStream fs = File.Create(@"k:\soapPicBinary2.gif");
fs.Write(bb, 0, bb.Length);
fs.Close();
}
在网站项目上右键,然后在右键菜单中可以看到WSE设置:WSE settings 3.0
这个可视化的工具是对Web.config文件的配置工具,WSE配置选项是放在web.config文件中的。
·在常规选项卡上,把增强选项和WSE soap协议工厂选中。
·在消息选项卡上,在MTOM设置中把客户模式选择打开。
然后就可以发布了。
(二) 客户端
在客户端添加web服务引用,生成代理,同时也要进行wse设置,这个比较简单,只要在消息选项卡上,把MTOM设置中的客户模式打开就行。如果是网站项目,会自动在Web.config文件中添加必要的章节,如果是应用程序,会在app.config文件中添加章节。
例如,现在在类库项目中添加wse服务引用,设置3.0后,app.config内容如下:
添加
<section name="microsoft.web.services3"
type="Microsoft.Web.Services3.
Configuration.WebServicesConfiguration, Microsoft.Web.Services3,
Version=
章节,此节定义消息模式:
<microsoft.web.services3>
<messaging>
<mtom clientMode="On" serverMode="always" />
</messaging>
</microsoft.web.services3>
测试代码:
public void TestWse()
{
FirstInstance.FirstServiceWse client =
new UTest.FirstInstance.FirstServiceWse();
FileStream fs = new FileStream(@"k:\x1.gif", FileMode.Open);
byte[] bb = new byte[fs.Length];
fs.Read(bb, 0, bb.Length);
client.SaveImage(bb);
}
现在客户端通过的就是WSE服务代理实例来实现WSE服务请求。会了区分WSE下的附件MTOM传输优化,现在先通过WS服务代理实例来实现附件传输:
只要改到实例就可以:
FirstInstance.FirstService client =
new UTest.FirstInstance.FirstService();
查看soap包:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<SaveImage xmlns="http://tempuri.org/">
<bb>R0lGODlhZGMDggAOw==</bb>
</SaveImage>
</soap:Body>
</soap:Envelope>
在包体的附件部分,我省略了大部分内容,但它是base64编码,与我在http://www.cnblogs.com/jams742003/archive/2010/03/31/1701555.html
中的附件的格式相同。
下面是启用了MTOM传输的WSE服务代理实例下的soap包:
----MIMEBoundary634057127108593750
content-id: <0.634057127108593750@example.org>
content-type: application/xop+xml; charset=utf-8; type="text/xml; charset=utf-8"
content-transfer-encoding: binary
<soap:Envelope
xmlns:xop="http://www.w3.org/2004/08/xop/include"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/
01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soap:Header>
</soap:Header>
<soap:Body>
<SaveImage xmlns="http://tempuri.org/">
<bb>
<xop:Include href="cid:1.634057127108906250@example.org" />
</bb>
</SaveImage>
</soap:Body>
</soap:Envelope>
----MIMEBoundary634057127108593750
content-id: <1.634057127108906250@example.org>
content-type: application/octet-stream
content-transfer-encoding: binary
GIF89ad
----MIMEBoundary634057127108593750—
可以看到所谓的MTOM优化传输包的形式。
Web service,或是WSE以soap协议(包)来传递消息,消息是重要的,也是目的所在。精确的控制消息,或说精准的控制包的内容是最主要的任务。
Soap协议版本从1.1到1.2有一些改进,消除了以前所存在的歧义,使解析更明确。.net web 服务及WSE就是遵循soap协议规则而用于控制soap包的简便工具。
现在实现传递附件和客户实例
服务端:
[WebMethod]
public void SaveImage(byte[] bb)
{
FileStream fs = File.Create(@"k:\soapPicBinary3.gif");
fs.Write(bb, 0, bb.Length);
fs.Close();
}
[WebMethod]
public void SaveAttachments(byte[] bb,Customer customer)
{
SaveImage(bb);
CreateText(customer);
}
private void CreateText(Customer customer)
{
StreamWriter writer= File.CreateText(@"k:\customer.txt");
writer.Write(customer.Unid.ToString()
+ ":" + customer.UserName
+ " " + customer.CreateTime.ToString());
writer.Close();
}
其中加粗的方法是进行测试的方法。
在客户端:
public void TestCustomer()
{
FirstInstance.Customer customer =
new UTest.FirstInstance.Customer();
customer.Unid = 2;
customer.UserName = "Songjiang";
customer.CreateTime = Convert.ToDateTime("
FileStream fs = new FileStream(@"k:\x1.gif", FileMode.Open);
byte[] bb = new byte[fs.Length];
fs.Read(bb, 0, bb.Length);
fs.Close();
FirstInstance.FirstServiceWse client =
new UTest.FirstInstance.FirstServiceWse();
client.SaveAttachments(bb, customer);
}
包的形式大概也能猜出来,现在只取包体一段内容:
<soap:Body>
<SaveAttachments xmlns="http://tempuri.org/">
<bb>
<xop:Include href="cid:1.634057142194062500@example.org" />
</bb>
<customer>
<Unid>2</Unid>
<UserName>Songjiang</UserName>
<CreateTime>
</customer>
</SaveAttachments>
</soap:Body>
其中的客户还是以原来的格式存储,而附件(图片)是以MTOM形式存在发送。
消息是主体,消息就是包,精准的控制包的各个部分及命名要根据工具的控制力和自己的深入程度来达到。.net ws做为微软的ws工具,是不支持MIME附件soap包的,但在WSE2中就支持了对DIME附件的控制,在3.0中又支持了MTOM传输,这是工具的控制力;在WCF中,对于信道,信道元素,绑定模型等深层内容的掌握就是程序员深入理解和构建包的有力条件。尽管在我们的应用层面上,WCF对我们的大部分应用已经胜任且绰绰有余,但更深入的研究、理解和应用只有好处。轮子并不要我们创造,但从割胶到提取加工,以至到轮胎成型,如果整个过程我们理解的话,也不是坏事的,这样最少有2个好处:对于不同路面的轮胎可以进行不同处理而提供最恰当的轮胎(尽管差一点的轮胎也能上路);谁知道什么时候要做一回鲁宾逊?
例如,为服务的方法添加名字空间:
<SaveAttachments xmlns="http://tempuri.org/">
这个可以在web服务的类中添加修饰标签来达到:
[WebService(Namespace = "http://tempuri.org/")]