c#相关资料——动态调用Webservice例子

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

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

在.NET Framework 的System.Web.Services.Description 命名空间中有我们需要的东西。

具体步骤:
1. 从目标URL 下载WSDL 数据。

2. 使用ServiceDescription 创建和格式化WSDL 文档文件。

3. 使用ServiceDescriptionImporter 创建客户端代理类。

4. 使用CodeDom 动态创建客户端代理类程序集。

5. 利用反射调用相关WebService 方法。

/// <summary>
/// Summary description for Service1
/// </summary>
[WebService(Namespace = "/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
public class ProcessFlow : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
}
1. 动态调用WebService
客户端动态调用代码
using System.IO;
using ;
using System.Reflection;
using System.CodeDom;
using piler;
using System.Web.Services;
using System.Web.Services.Description;
using System.Web.Services.Protocols;
using System.Xml.Serialization;
// 1. 使用 WebClient 下载 WSDL 信息。

WebClient web = new WebClient();
Stream stream = web.OpenRead("http://localhost/FlowEngine/ProcessFlow.asmx?WSDL");
// 2. 创建和格式化 WSDL 文档。

ServiceDescription description = ServiceDescription.Read(stream);
// 3. 创建客户端代理代理类。

ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
importer.ProtocolName = "Soap"; // 指定访问协议。

importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。

importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerati onOptions.GenerateNewAsync;
importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档。

// 4. 使用 CodeDom 编译客户端代理类。

CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间,缺省为全局空间。

CodeCompileUnit unit = new CodeCompileUnit();
spaces.Add(nmspace);
ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit); CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters parameter = new CompilerParameters();
parameter.GenerateExecutable = false;
parameter.GenerateInMemory = true;
parameter.ReferencedAssemblies.Add("System.dll");
parameter.ReferencedAssemblies.Add("System.XML.dll");
parameter.ReferencedAssemblies.Add("System.Web.Services.dll");
parameter.ReferencedAssemblies.Add("System.Data.dll");
CompilerResults result = pileAssemblyFromDom(parameter, unit);
// 5. 使用 Reflection 调用 WebService。

if (!result.Errors.HasErrors)
{
Assembly asm = piledAssembly;
Type t = asm.GetType("ProcessFlowController"); // 如果在前面为代理类添加了命名空间,此处需要将命名空间添加到类型前面。

object o = Activator.CreateInstance(t);
MethodInfo method = t.GetMethod("HelloWorld");
Console.WriteLine(method.Invoke(o, null));
2. 生成客户端代理程序集文件
上面的代码通过在内存中创建动态程序集的方式完成了动态调用过程。

如果我们希望将客户端代理类生成程序集文件保存到硬盘,则可以进行如下修改。

生成程序集文件后,我们可以通过Assembly.LoadFrom() 载入并进行反射调用。

对于需要多次调用的系统,要比每次生成动态程序集效率高出很多。

Code
using System.IO;
using ;
using System.CodeDom;
using piler;
using System.Web.Services;
using System.Web.Services.Description;
using System.Web.Services.Protocols;
using System.Xml.Serialization;
// 1. 使用 WebClient 下载 WSDL 信息。

WebClient web = new WebClient();
Stream stream = web.OpenRead("http://localhost/FlowEngine/ProcessFlow.asmx?WSDL");
// 2. 创建和格式化 WSDL 文档。

ServiceDescription description = ServiceDescription.Read(stream);
// 3. 创建客户端代理代理类。

ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
importer.ProtocolName = "Soap"; // 指定访问协议。

importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。

importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerati onOptions.GenerateNewAsync;
importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档。

// 4. 使用 CodeDom 编译客户端代理类。

CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间,缺省为全局空间。

CodeCompileUnit unit = new CodeCompileUnit();
spaces.Add(nmspace);
ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit); CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters parameter = new CompilerParameters();
parameter.GenerateExecutable = false;
parameter.OutputAssembly = "test.dll"; // 可以指定你所需的任何文件名。

parameter.ReferencedAssemblies.Add("System.dll");
parameter.ReferencedAssemblies.Add("System.XML.dll");
parameter.ReferencedAssemblies.Add("System.Web.Services.dll");
parameter.ReferencedAssemblies.Add("System.Data.dll");
CompilerResults result = pileAssemblyFromDom(parameter, unit);
if (result.Errors.HasErrors)
{
// 显示编译错误信息
}
调用程序集文件演示
Assembly asm = Assembly.LoadFrom("test.dll");
Type t = asm.GetType("WProcessFlowController");
object o = Activator.CreateInstance(t);
MethodInfo method = t.GetMethod("HelloWorld");
Console.WriteLine(method.Invoke(o, null));
3. 获取客户端代理类源代码
还有一种情形,就是我们需要获得客户端代理类的C# 源代码。

Code
using System.IO;
using ;
using System.CodeDom;
using piler;
using System.Web.Services;
using System.Web.Services.Description;
using System.Web.Services.Protocols;
using System.Xml.Serialization;
// 1. 使用 WebClient 下载 WSDL 信息。

WebClient web = new WebClient();
Stream stream = web.OpenRead("http://localhost/FlowEngine/ProcessFlow.asmx?wsdl");
// 2. 创建和格式化 WSDL 文档。

ServiceDescription description = ServiceDescription.Read(stream);
// 3. 创建客户端代理代理类。

ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
importer.ProtocolName = "Soap"; // 指定访问协议。

importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。

importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerati onOptions.GenerateNewAsync;
importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档。

// 4. 使用 CodeDom 编译客户端代理类。

CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间,缺省为全局空间。

CodeCompileUnit unit = new CodeCompileUnit();
spaces.Add(nmspace);
ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit); CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
// 5. 保存源代码到文件。

当然,你也可以直接保存到内存字符串中。

TextWriter writer = File.CreateText("test.cs"); // 指定你所需的源代码文件名。

provider.GenerateCodeFromCompileUnit(unit, writer, null);
writer.Flush();
writer.Close();
如果你调用时触发 "WebException: 请求因 HTTP 状态 415 失败: Unsupported Media Type。

" 这样的异常,赶紧把服务器端的 WSE 关掉吧。

在必须使用 WSE 的情况下,需要对客户端进行调整,至于代码需要你自己去写了。

呵呵~~~~
最后:整理一下第一种情况下的一个方法:
Code
/// <summary>
/// 根据指定的信息,调用远程WebService方法
/// </summary>
/// <param name="url">WebService的http形式的地址</param>
/// <param name="namespace">欲调用的WebService的命名空间</param>
/// <param name="classname">欲调用的WebService的类名(不包括命名空间前缀)</param> /// <param name="methodname">欲调用的WebService的方法名</param>
/// <param name="args">参数列表</param>
/// <returns>WebService的执行结果</returns>
/// <remarks>
/// 如果调用失败,将会抛出Exception。

请调用的时候,适当截获异常。

/// 异常信息可能会发生在两个地方:
/// 1、动态构造WebService的时候,CompileAssembly失败。

/// 2、WebService本身执行失败。

/// </remarks>
/// <example>
/// <code>
/// object obj = InvokeWebservice("http://localhost/GSP_WorkflowWebservice/common.asmx", /// "Genersoft.Platform.Service.Workflow",
/// "Common",
/// "GetToolType",
/// new object[]{"1"});
/// </code>
/// </example>
public static object InvokeWebservice(string url, string @namespace, string classname,
string methodname, object[] args)
{
try
{
.WebClient wc = new .WebClient();
System.IO.Stream stream = wc.OpenRead(url + "?WSDL");
System.Web.Services.Description.ServiceDescription sd
= System.Web.Services.Description.ServiceDescription.Read(stream);
System.Web.Services.Description.ServiceDescriptionImporter sdi
= new System.Web.Services.Description.ServiceDescriptionImporter();
sdi.AddServiceDescription(sd, "", "");
System.CodeDom.CodeNamespace cn = new System.CodeDom.CodeNamespace(@namespa ce);
System.CodeDom.CodeCompileUnit ccu = new System.CodeDom.CodeCompileUnit();
spaces.Add(cn);
sdi.Import(cn, ccu);
Microsoft.CSharp.CSharpCodeProvider csc = new Microsoft.CSharp.CSharpCodeProvider(); piler.ICodeCompiler icc = csc.CreateCompiler();
pilerParameters cplist
= new pilerParameters();
cplist.GenerateExecutable = false;
cplist.GenerateInMemory = true;
cplist.ReferencedAssemblies.Add("System.dll");
cplist.ReferencedAssemblies.Add("System.XML.dll");
cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
cplist.ReferencedAssemblies.Add("System.Data.dll");
pilerResults cr = pileAssemblyFromDom(cplist, ccu); if (true == cr.Errors.HasErrors)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (pilerError ce in cr.Errors)
{
sb.Append(ce.ToString());
sb.Append(System.Environment.NewLine);
}
throw new Exception(sb.ToString());
}
System.Reflection.Assembly assembly = piledAssembly;
Type t = assembly.GetType(@namespace + "." + classname, true, true);
object obj = Activator.CreateInstance(t);
System.Reflection.MethodInfo mi = t.GetMethod(methodname);
return mi.Invoke(obj, args);
}
catch (Exception ex)
{
throw new Exception(ex.InnerException.Message, new Exception(ex.InnerException.StackTra ce));
}
}。

相关文档
最新文档