英文原文章地址:http://www.codeproject.com/KB/cpp/CallWebServicesDynamic.aspx。 (部分不影响理解的话未翻译到此)
摘要:
本文介绍如何在VS2005 IDE中不通过添加web应用来实现webService的动态调用。
背景:
你可能会在多种场合遇到这种需求,我能想到有以下两种,应用这种方法得心应手。
- 在Application Service Provider Model 中的松耦合集成。 Application Service Provider Model 是指单一的web application 可以支持来自不同客户端的用户。
在这种情况下,应用程序需要根据不同的客户来调用不同的相互独立的webService。如果每一个webService都要添加引用,这是一个不大好的注意,尤其在这些service具有相同规范的情况下。
- 运行时动态调用不同的webservice。 假想有两个或者更多的webservice 他们具有相同的wsdl 用法却有不同的功能和内部实现,当应用程序需要在运行时依据具体实际需要调用相应的服务的时候,这种方法会很有效。
范例
为了简单起见,我们尽量删除复杂的逻辑部分。我们省去了余数据库交互的代码,重点讲注意力集中到本文的主题:不添加web引用,调用webservice。假设有一个叫WelcomeUser得程序,它符合Application Service Provider这里的 Model 标准。此程序需要让来自不同公司 例如"Foo" and "XFoo", 的用户,登陆进来。
然而,实际的应用程序是web 程序,它通过调用部署在Foo and XFoo公司而且进行独立维护的service实现给不同公司用户现实不同的欢迎消息。这个程序的开发着们不想去部署 维护 每个不同客户端的服务,他们想尽量做到松耦合。
尽管只是让每个公司去写出自己欢迎消息的想法听起来有些小题大作,我们假设这种欢迎信息是基于两者公司不同的数据库环境之上加上复杂的逻辑处理得到的。
设计WSDL,分布的客户端以及他们自身的实现
由于WelcomeUser 应用程序需要根据不同公司的用户调用不同的webservice,所以开发者应该在写webservice之前确定下来Foo" and "XFoo 都应该遵守的WSDL规范。
这里的wsdl 低耦合的契约,类似OOP中的接口。
开发者随即写了一个webservice 命名WelcomeMessageStub 包含方法"GetWelcomeMessage()
". 示例代码如下
[WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class WelcomeMessageStub : System.Web.Services.WebService { public WelcomeMessageStub () { } [WebMethod] public string GetWelcomeMessage() { return "The Welcome Message That You Need To Return"; } }
接下来,我们通过访问"[URL Of the Web Service]/WelcomeMessageStub.asmx?wsdl", 来使用和发布WSDL 规范Foo" and "XFoo 两个公司的客户端。这里应该指出
有多种工具不需要一定编码就可以生成WSDL规范。这里之所以这样做是想集中精力解决本文开头提出的问题。
下面我们假设Foo 公司的开发者实现WSDL规范如下编码:
[WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class WelcomeMessageFoo : System.Web.Services.WebService { public WelcomeMessageFoo () { } [WebMethod] public string GetWelcomeMessage() { return "Welcome to Foo!"; } }
xFoo公司开发者则有不同的实现如下
[WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class WelcomeMessageXFoo : System.Web.Services.WebService { public WelcomeMessageXFoo () { } [WebMethod] public string GetWelcomeMessage() { return "Welcome to XFoo User!"; } }
假设这两个不同的webservice 宿主在不同的url 而且他们都遵守Application Service Provider Model 模型。具体来说,来自Foo公司的用户需要Foo实现的url,而来自
XFOO公司的用户也需要调用自己的url 实现。尽管这个例子非常简单,但是这是解决方法是通用的,适用于复杂的情况。
完成WelcomeUser应用程序
开始之前,我们来了解一下webservice工作的基本原理和当你在Visual Studio .NET 2005 IDE添加webservice引用时,IDE所做的幕后工作。当你在IDE中设置一个webservice引用时,IDE会为你一个代理类,这个代理类基于WSDL规范,代表了远程服务器上的webservice类。如果你曾经对于每次更新webservice引用时,智能感知就变得不那么精确
的现象感到困惑,现在就应该知道了那是因为那些关于webservice的智能感知是V由isual Studio 生成的代理类提供商。当你在client端调用webservice的时候,你所做的仅仅是
在本地调用代理类的方法而已,代理类实际调用远程Web Service URL的方法。所以每次webservice更新时候 代理类都需要重新生成。然而,通过IDE生成代理类并不是唯一的
方法,,net给我们提供了WSDL.exe 工具可以手动生成代理类。
既然我们已经了解了webservice的原理呢IDE所做的处理,就言归正传开始写我们的WelcomeUser 应用程序。首先我们创建WelcomeMessageStub 的代理类。然后使用代理类
调用Foo and xFoo 各自的url。
使用WSDL.exe 工具在命令行中如下操作
说明一点,WSDL.exe 是基于WSDL 规范生成的WelcomeMessageStub.cs。完成之后,我们快速创建一个website,把代码放到App_Code 目录下。
到此也许我们应该去剖析一下这个生成的代理类代码啦。为了集中精力解决问题,我们只是简单看一下如下代码即可。
public WelcomeMessageStub<CODE>()</CODE> {
this.Url = "http://localhost/WelcomeMessageStub/WelcomeMessageStub.asmx";
}
值得一提的是,这个默认的构造函数包含了webservice宿主的url。但是这个url是可以在运行时动态改变的。下面的代码片段展示了Foo and xFoo 客户端如何
动态调用代理类、
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// We Can use Database or other Mechanisms to select which company
// the user belongs to. Once this
// is done we can have a small IF construct
// to invoke the right web service from the right URL.
// Without going into those complications the below code displays how we
// can call two different Web Services using the same proxy Class.
WelcomeMessageStub welcomeMessageStub = new WelcomeMessageStub();
// IF the User Belongs to Foo - Lets Hit Foo's Web Service URL to Invoke
// the right Web Method on the fly.
welcomeMessageStub.Url =
"http://localhost/WelcomeMessageStub/WelcomeMessageFoo.asmx";
Response.Write(welcomeMessageStub.GetWelcomeMessage());
Response.Write("<br/>");
// However IF we found out that the user Belongs
// too xFoo we could Hit xFoo's Web Service
// URL to Invoke the right Web Method on the fly.
// The URLs can be COMPLETELY different as
// long as they are reachable.
welcomeMessageStub.Url =
"http://localhost/WelcomeMessageStub/WelcomeMessagexFoo.asmx";
Response.Write(welcomeMessageStub.GetWelcomeMessage());
}
}
完