C# .NET 动态调用webservice的三种方式

转载自 百度文库
http://wenku.baidu.com/link?url=Q2q50wohf5W6UX44zqotXFEe_XOMaib4UtI3BigaNwipOHKNETloMF4ax4W4iPZcjAW6q8vu45QOjK6DSUon1R10ePVlqG6nwussbbXE6jm

多数时候我们通过 "添加 Web 引用..."
创建客户端代理类的方式调用WebService,但在某些情况下我们可能需要在程序运行期间动态调用一个未知的服务。在 .NET Framework 的
System.Web.Services.Description 命名空间中有我们需要的东西。

具体步骤:

1. 从目标 URL 下载
WSDL 数据。
2. 使用 ServiceDescription 创建和格式化 WSDL 文档文件。
3. 使用
ServiceDescriptionImporter 创建客户端代理类。
4. 使用 CodeDom 动态创建客户端代理类程序集。
5.
利用反射调用相关 WebService 方法。

上述步骤需要引用如下四个名称空间:

using System.Web.Services.Description; //WS的描述

//以下几个用于根据描述动态生成代码并动态编译获取程序集

using System.CodeDom;

using Microsoft.CSharp;

using System.CodeDom.Compiler;

上述几个名称空间中包括如下几个重要的类:

using System.Web.Services.Description下:

ServiceDescription //WS描述

ServiceDescriptionImporter //通过描述生成客户端代理类,特别注意其中的Style

以下是MSDN对其的描述:

XML Web services 的接口通常由 Web 服务描述语言 (WSDL) 文件来说明。例如,若要获取有关使用
http://localhost/service.asmx 处公开的 ASP.NET 的 Web 服务的 WSDL 说明,只需导航到
http://localhost/service.asmx?WSDL。使用ServiceDescriptionImporter 类可以方便地将 WSDL
说明中包含的信息导入到 System.CodeDom.CodeCompileUnit 对象。通过调整 Style 参数的值,可以指示
ServiceDescriptionImporter 实例生成客户端代理类(通过透明调用该类可提供 Web 服务的功能)或生成抽象类(该类封装 Web
服务的功能而不实现该功能)。如果将 Style 属性设置为 Client,则 ServiceDescriptionImporter
生成客户端代理类,通过调用这些类来提供说明的 Web 服务的功能。如果将 Style 属性设置为 Server,则
ServiceDescriptionImporter 实例生成抽象类,这些类表示所说明的 XML Web services
的功能而不进行实现。然后,可以通过编写从这些抽象类继承的类来对其进行实现,并实现相关的方法。

using System.CodeDom下:

CodedomUnit
//它用于设定动态代码的名称空间,类名等,可以通过ServiceDescriptionImporter.Import()方法将WS的描述代码写入该类,以作动态编译用

using System.CodeDom.Compiler下:

CodedomProvider //用于创建和检索代码生成器和代码编译器的实例,我们主要用到其实现子类CShareCodeProvider

可以直接用CShareCodeProvider provider=new
CShareCodeProvider()来生成,或者用CodedomProvider.CreateProvider("CSharp")来生成

ICodeCompiler //用于编译基于System.CodeDom 的源代码表示形式。

它通过CodedomProvider的CreateCompiler()方法来

CompilerResults //表示从编译器返回的编译结果。 它由ICodeCompiler根据指定的编译器设置从指定的
CodeCompileUnit 所包含的 System.CodeDom 树中编译程序集并返回。CompiledAssembly 属性指示编译的程序集。

了解如上信息后,就可动态调用WS了。

OK,看看具体的例子。

我们要调用的目标 WebService,其 URL 是 http://localhost:60436/Learn.WEB/WebService.asmx

HelloWorld.asmx


 1 [WebService(Namespace = "http://www.rainsts.net/", Description="我的Web服务")]
2 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
3 public class WebService : System.Web.Services.WebService {
4
5 public WebService () {
6 }
7
8 [WebMethod]
9 public string HelloWorld()
10 {
11 return "Hello Wolrd!";
12 }
13 }

1. 动态调用 WebService

客户端动态调用代码


 1 using System.IO;
2 using System.Net;
3 using System.Reflection;
4 using System.CodeDom;
5 using System.CodeDom.Compiler;
6 using System.Web.Services;
7 using System.Web.Services.Description;
8 using System.Web.Services.Protocols;
9 using System.Xml.Serialization;
10
11 // 1. 使用 WebClient 下载 WSDL 信息。
12 WebClient web = new WebClient();
13 Stream stream = web.OpenRead("http://localhost:60436/Learn.WEB/WebService.asmx?WSDL");
14
15 // 2. 创建和格式化 WSDL 文档。
16 ServiceDescription description = ServiceDescription.Read(stream);
17
18 // 3. 创建客户端代理代理类。
19 ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
20
21 importer.ProtocolName = "Soap"; // 指定访问协议。
22 importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。
23 importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;
24
25 importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档。
26
27 // 4. 使用 CodeDom 编译客户端代理类。
28 CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间,缺省为全局空间。
29 CodeCompileUnit unit = new CodeCompileUnit();
30 unit.Namespaces.Add(nmspace);
31
32 ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);
33 CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
34
35 CompilerParameters parameter = new CompilerParameters();
36 parameter.GenerateExecutable = false;
37 parameter.GenerateInMemory = true;
38 parameter.ReferencedAssemblies.Add("System.dll");
39 parameter.ReferencedAssemblies.Add("System.XML.dll");
40 parameter.ReferencedAssemblies.Add("System.Web.Services.dll");
41 parameter.ReferencedAssemblies.Add("System.Data.dll");
42
43 CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit);
44
45 // 5. 使用 Reflection 调用 WebService。
46 if (!result.Errors.HasErrors)
47 {
48 Assembly asm = result.CompiledAssembly;
49 Type t = asm.GetType("WebService"); // 如果在前面为代理类添加了命名空间,此处需要将命名空间添加到类型前面。
50
51 object o = Activator.CreateInstance(t);
52 MethodInfo method = t.GetMethod("HelloWorld");
53 Console.WriteLine(method.Invoke(o, null));
54 }

2. 生成客户端代理程序集文件

上面的代码通过在内存中创建动态程序集的方
式完成了动态调用过程。如果我们希望将客户端代理类生成程序集文件保存到硬盘,则可以进行如下修改。生成程序集文件后,我们可以通过
Assembly.LoadFrom() 载入并进行反射调用。对于需要多次调用的系统,要比每次生成动态程序集效率高出很多。


 1 using System.IO;
2 using System.Net;
3 using System.CodeDom;
4 using System.CodeDom.Compiler;
5 using System.Web.Services;
6 using System.Web.Services.Description;
7 using System.Web.Services.Protocols;
8 using System.Xml.Serialization;
9
10 // 1. 使用 WebClient 下载 WSDL 信息。
11 WebClient web = new WebClient();
12 Stream stream = web.OpenRead("http://localhost:60436/Learn.WEB/WebService.asmx?WSDL");
13
14 // 2. 创建和格式化 WSDL 文档。
15 ServiceDescription description = ServiceDescription.Read(stream);
16
17 // 3. 创建客户端代理代理类。
18 ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
19
20 importer.ProtocolName = "Soap"; // 指定访问协议。
21 importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。
22 importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;
23
24 importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档。
25
26 // 4. 使用 CodeDom 编译客户端代理类。
27 CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间,缺省为全局空间。
28 CodeCompileUnit unit = new CodeCompileUnit();
29 unit.Namespaces.Add(nmspace);
30
31 ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);
32 CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
33
34 CompilerParameters parameter = new CompilerParameters();
35 parameter.GenerateExecutable = false;
36 parameter.OutputAssembly = "test.dll"; // 可以指定你所需的任何文件名。
37 parameter.ReferencedAssemblies.Add("System.dll");
38 parameter.ReferencedAssemblies.Add("System.XML.dll");
39 parameter.ReferencedAssemblies.Add("System.Web.Services.dll");
40 parameter.ReferencedAssemblies.Add("System.Data.dll");
41
42 CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit);
43 if (result.Errors.HasErrors)
44 {
45 // 显示编译错误信息
46 }
47
48 调用程序集文件演示
49 Assembly asm = Assembly.LoadFrom("test.dll");
50 Type t = asm.GetType("WebService");
51
52 object o = Activator.CreateInstance(t);
53 MethodInfo method = t.GetMethod("HelloWorld");
54 Console.WriteLine(method.Invoke(o, null));

3. 获取客户端代理类源代码

还有一种情形,就是我们需要获得客户端代理类的 C# 源代码。


 1 using System.IO;
2 using System.Net;
3 using System.CodeDom;
4 using System.CodeDom.Compiler;
5 using System.Web.Services;
6 using System.Web.Services.Description;
7 using System.Web.Services.Protocols;
8 using System.Xml.Serialization;
9
10 // 1. 使用 WebClient 下载 WSDL 信息。
11 WebClient web = new WebClient();
12 Stream stream = web.OpenRead("http://localhost:60436/Learn.WEB/WebService.asmx?WSDL");
13
14 // 2. 创建和格式化 WSDL 文档。
15 ServiceDescription description = ServiceDescription.Read(stream);
16
17 // 3. 创建客户端代理代理类。
18 ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
19
20 importer.ProtocolName = "Soap"; // 指定访问协议。
21 importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。
22 importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;
23
24 importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档。
25
26 // 4. 使用 CodeDom 编译客户端代理类。
27 CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间,缺省为全局空间。
28 CodeCompileUnit unit = new CodeCompileUnit();
29 unit.Namespaces.Add(nmspace);
30
31 ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);
32 CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
33
34 // 5. 保存源代码到文件。当然,你也可以直接保存到内存字符串中。
35 TextWriter writer = File.CreateText("test.cs"); // 指定你所需的源代码文件名。
36 provider.GenerateCodeFromCompileUnit(unit, writer, null);
37 writer.Flush();
38 writer.Close();

如果你调用时触发 "WebException: 请求因 HTTP 状态 415 失败: Unsupported Media Type。"
这样的异常,那么恭喜你和我一样郁闷 ,赶紧把服务器端的 WSE 关掉吧。在必须使用 WSE
的情况下,需要对客户端进行调整,至于代码需要你自己去写了。呵呵~~~~

时间: 2024-10-12 16:17:25

C# .NET 动态调用webservice的三种方式的相关文章

java动态获取WebService的两种方式(复杂参数类型)

java动态获取WebService的两种方式(复杂参数类型) 第一种: @Override public OrderSearchListRes searchOrderList(Order_FlightOrderSearchRequest request) { Object myAllMessage; OrderSearchListRes response = null; try { String endpoint = carGlobalSetting.getEndpoint(); JaxWsD

C# 调用WebService的3种方式 :直接调用、根据wsdl生成webservice的.cs文件及生成dll C#调用、动态调用

1.直接调用 已知webservice路径,则可以直接 添加服务引用--高级--添加web引用 直接输入webservice URL.这个比较常见也很简单 即有完整的webservice文件目录如下图所示, 也可以在本地IIS根据webservice文件目录新发布一个webservice,然后程序动态调用,修改Url public new string Url { set; get; } 2.根据wsdl文件生成webservice 的.cs文件 及 生成dll C#调用   有时没有这么多文件

【SSH三大框架】Struts2基础第三篇:配置Action以及调用Action的三种方式

一.struts.xml中的包和命名空间 1.Struts2不支持为单独的Action设置命名空间,而是通过为包指定namespace属性来为包下面的所有Action指定共同的命名空间. 如果在配置<package>的时候没有指定namespace属性,则该包下的所有Action处于默认的包空间下 2.例如: <package name="lee" extends="struts-default"> <action name="

调用webService的几种方式

转自:http://blog.csdn.net/u011165335/article/details/51345224 一.概览 方式1: HttpClient:可以用来调用webservie服务,也可以抓取网页数据 版本1:HttpClient3.0.x 版本2:HttpClient4.x.x(目前最新4.5.2) 这2个版本的使用方式不一样:变动较大 方式2:纯Java(自带API)      jws 方式3:cxf框架 方式4:axis2框架 准备工作: 1.了解wsimport    

Atitit 动态调用webservice与客户端代理方式调用

方式1: 使用call.invoke  直接调用WSDL,缺点:麻烦,不推荐--特别是JAVA调用.NET的WS时,会有不少的问题需要解决. 方式2: 生成测试STUB--此种方法更快捷.如果用.NET开发WS客户端,就是用的这种方式-- 客户端调用web service方法首先要使用cxf的wsdl2java命令工具生成服务代理类,如:wsdl2java -p com.charles.client http://localhost:8080/queryUser?wsdl具体命令格式可使用wsd

java调用webservice的四种方式

webservice: 就是应用程序之间跨语言的调用 wwww.webxml.com.cn 1.xml 2.    wsdl: webservice description language web服务描述语言 通过xml格式说明调用的地址方法如何调用,可以看错webservice的说明书 3.soap simple object access protoacl (简单对象访问协议) 限定了xml的格式 soap 在http(因为有请求体,所以必须是post请求)的基础上传输xml数据 请求和响

JS调用webservice的两种方式

协议肯定是使用http协议,因为soap协议本身也是基于http协议.期中第二种方式:只有webservice3.5以后版本才可以成功 第一种方式:构造soap格式的body,注意加粗的黄色标识,比如: createXMLHttpRequest();     var data;     data = '<?xml version="1.0" encoding="utf-8"?>';     data = data + '<soap:Envelope

C#调用Webservice的几种方式

1-添加服务引用: (1)工程 - Service References - 添加服务引用: (2)在“添加服务引用”中输入Webservice网站发布地址,并敲回车或点击“转到”: (3)调用代码编写 实现方式:ServiceReference1.Service1SoapClient ser1 = new ServiceReference1.Service1SoapClient("Service1SoapClient"); using System; using System.Col

调用数据库的三种方式

ThinkPHP 内置了抽象数据库访问层,把不同的数据库操作封装起来.我们只需要使用公共的 Db 类进行操作,无须针对不同的数据库写不同的代码和底层实现.Db 类会自动调用相应的数据库驱动来处理. 一.全局配置定义   在 common/conf/config.php 中 'DB_TYPE'=>'mysql', //数据库类型 'DB_HOST'=>'localhost', //服务器地址 'DB_NAME'=>'thinkphp', //数据库名 'DB_USER'=>'root