一:概要
1. wse1.0 sp1
wse(web services enhancements) 是微软提供的一个实现了ws-security, ws-routing, ws-attachments and dime 等标准的组件(dll)。它使得开发人员可以不需要深入了解上述协议的具体内容就可以开发相应的web services 程序,大大简化了开发难度,使得web services应用在企业级项目上成为可能。
2. 常用的几个用途
▲ 添加/修改自定义的soap header
▲ 加入身分验证
▲ 加密soapbody信息
▲ 使用附件
▲ 添加soap router信息
二:设计
2.1 项目的提出:
在一个网上采购系统中,每一个供货方提供给采购方一个webservices,其中有一个提供货物清单的webmethod。这个webmethod的名字可以是不一样的,但其都提供相同的接口。这里,我们假定需要两个入口参数,返回一个string 类型的xml文件。至于为什么假定需要两个参数,在本文后面当有介绍。在实际实现中,接口是可以制定相应规范的,这样也就可以最大限度的重用proxy了。
一个采购方希望可以得到最佳的采购方案(本文只讨论技术层次,人际关系,公司关系等不做研究),那么它就会尽可能多的加入更多的供货方。有可能的情况是每天都会有新的供货方加入,因此需要采购方系统是一个可扩展的系统。在本例中,当采购方需要查询一个部件的供货信息的时候,它将使用一个名为getallproduct(string name)的方法来呼叫所有的webservices,并将得到的返回结果汇总显示。由于本文只是以介绍wse为主,因此不过多讨论系统设计的问题。因为这个项目是我临时杜撰出来,因此在很多方面都不完善,不过我只是描述wse在使用方法,是一个纯粹的技术的讨论。
由于随时都会有新的webservice被加入,因此如果我们利用添加web引用的方式加入web services,那么就把程序写得很死,失去了灵活性和扩展性。因此,我们需要由程序根据webservices的wsdl来生成proxy,并编译成相应的dll。这里,我们可以人为的定义一个serviceid作为主键来唯一指定一个webservices。在实际开发中,我们将使用proxy,factory设计模式来进行系统设计,将不同的wdsl的proxy的生成,proxy的构造封装成相对独立的模块。我们将使用wsdl.exe应用程序,以及.net reflecting(反射)的功能 实现。
在调用webservice或者接收返回信息的时候,我们可能需要加入一些额外的东西,例如身份认证,定制的soapheader,加密等操作,这里我将使用微软提供的wse1.0来实现。具体如何实现可以参考微软提供的quickstart的例子。其包含在wse1.0sp1的下载包中,具体位置如下:
http://www.microsoft.com/downloads/details.aspx?familyid=06255a94-2635-4d29-a90c-28b282993a41&displaylang=en
2.2 proxy 的产生以及使用
1. 根据wsdl自动生成proxy文件(prxoyfactory,使用wsdl.exe)
可以自己制作一个工具,用来根据提供的wsdl地址生成proxy的cs文件。主要代码如下所示:
string parameter = wsdlurl;
parameter += " /l:c#";
parameter += " /n:" + serviceid;
parameter += " /o:" + constants.library_path + "\\" + serviceid + ".cs";
// use serviceid as output file name
try
{
processstartinfo startinfo = new processstartinfo(constants.wsdl_path, parameter);
process process = process.start(startinfo);
process.waitforexit();
if (process.exitcode != 0)
throw new exception("generate proxy error");
return true;
}
catch (exception ex)
{
}
示例 2.1
2. 修改生成proxy文件,将原来的继承httpwebclientprotocol 改成microsoft.web.services.webservicesclientprotocol
3. 根据数据库内容,为不同的proxy添加不同的pipeline(pipelinefactory)
每一个proxy都会有一个微软提供的默认的pipeline。这个pipeline将包括了proxy需要使用到的outputfilter,inputfilter,并且所有的filter顺序至关重要。因此,我们在设计一个webservices 的时候将指定一个唯一的serviceid,并且将其需要使用的filter加入数据库相应的表中。表应该有这个filte的类型(i/o),顺序,名字等。:
4. 在proxy 中,invoke webservice的方法应该是根据不同的webmethod name而不同。
如下所示:
object[] results = this.invoke(pipeline.operationname, new object[] {
msgid,
sxml});
5. 如果要在asp.net webservice中加入filter,目前只能在global.asax文件的application_start()加入。因此,如果在一个webservice中提供了多个webmethod,并且,对于对于不同的webmethod可能需要不同的filter(也可能没有)。这种情况下,可以将webmethod分开,做成多个webservice。每一个global.asaz中的filter只对自己所在的visual folder的请求/响应起作用。
6. 需要注意的是如果我们需要在一个webservices server上面加入filter(提供解密,验证功能),那么我们有两种方法作为选择。一种是在global.asax文件中的application_start()加入全部的filter,另外一种是在web.config中加入。这样,所有对这个虚拟目录的soap请求都会经过这些filter。但是,如果这个webservices提供了两个webmethod,并且只有其中的一个需要filter,另外一个不需要,上述方法就无法实现了。如何可以动态的为每一个soap请求分配filter一直也是我想知道的问题(类似proxy请求端),大家谁知道的也可以告诉我,谢谢。
参考:http://msdn.microsoft.com/webservices/building/wse/default.aspx