C#动态调用WebService

C#调用WebService的方法介绍 上面我们说了如何使用静态引用的方式调用WebService,但是这种方式有一个缺点如果发布的WebService地址改变,那么就要重新添加WebService的引用。如果是现有的WebService发生了改变,也要更新现有的服务引用,这需要把代码放到现场才可以。在日常工作中,如果涉及到与第三方进行接口对接,有的会使用WebService的方式,这篇文章主要讲解在.NETFramework中如何调用WebService。这篇文章介绍了C#调用WebService的方法,文中通过示例代码介绍的非常详细。... 阅读详情

【整理,内容来源于网络及本人实践】

        前面整理了一篇关于VS2008实现简单的WebService的文章,但里面的调用是静态的,当服务地址更改后,需要重新编译程序,对于很多应用来说是不现实的。本文介绍一下C#动态调用WebService的方法。

1.实现

       写个叫WebServiceHelper的类

namespace webhelp
{
    using System;
    using System.Net;
    using System.IO;
    using System.CodeDom;
    using Microsoft.CSharp;
    using System.CodeDom.Compiler;
    using System.Web.Services.Description;
    using System.Web.Services.Protocols;
    public class WebServiceHelper
    {
        #region InvokeWebService

        public static object InvokeAndCallWebService(string url, string methodname, object[] args)
        {
            return WebServiceHelper.InvokeAndCallWebService(url, null, methodname, args);
        }
        public static object InvokeAndCallWebService(string url,/* string @namespace, */string classname, string methodname, object[] args)
        {
            string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling";
            if ((classname == null) || (classname == ""))
            {
                classname = WebServiceHelper.GetWsClassName(url);
            }

            try
            {
                //获取WSDL   
                WebClient webClient = new WebClient();
                Stream stream = webClient.OpenRead(url + "?WSDL");
                ServiceDescription description = ServiceDescription.Read(stream);
                ServiceDescriptionImporter descriptionImporter = new ServiceDescriptionImporter();
                descriptionImporter.AddServiceDescription(description, "", "");
                CodeNamespace codeNamespace = new CodeNamespace(@namespace);

                //生成客户端代理类代码   
                CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
                codeCompileUnit.Namespaces.Add(codeNamespace);
                descriptionImporter.Import(codeNamespace, codeCompileUnit);
                CSharpCodeProvider codeProvider = new CSharpCodeProvider();

                //设定编译参数   
                CompilerParameters compilerParameters = new CompilerParameters();
                compilerParameters.GenerateExecutable = false;
                compilerParameters.GenerateInMemory = true;
                compilerParameters.ReferencedAssemblies.Add("System.dll");
                compilerParameters.ReferencedAssemblies.Add("System.XML.dll");
                compilerParameters.ReferencedAssemblies.Add("System.Web.Services.dll");
                compilerParameters.ReferencedAssemblies.Add("System.Data.dll");

                //编译代理类   
                CompilerResults codeResult = codeProvider.CompileAssemblyFromDom(compilerParameters, codeCompileUnit);
                if (true == codeResult.Errors.HasErrors)
                {
                    System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
                    foreach (System.CodeDom.Compiler.CompilerError compileError in codeResult.Errors)
                    {
                        stringBuilder.Append(compileError.ToString());
                        stringBuilder.Append(System.Environment.NewLine);
                    }
                    throw new Exception(stringBuilder.ToString());
                }

                //生成代理实例,并调用方法   
                System.Reflection.Assembly assembly = codeResult.CompiledAssembly;
                Type @class = assembly.GetType(@namespace + "." + classname, true, true);
                object instance = Activator.CreateInstance(@class);
                System.Reflection.MethodInfo methorInfo = @class.GetMethod(methodname);

                return methorInfo.Invoke(instance, args);

            }
            catch (Exception ex)
            {
                throw new Exception(ex.InnerException.Message, new Exception(ex.InnerException.StackTrace));
            }
        }

        private static string GetWsClassName(string wsUrl)
        {
            string[] parts = wsUrl.Split('/');
            string[] pps = parts[parts.Length - 1].Split('.');

            return pps[0];
        }
        #endregion
    }
}

2.注意

1.)若编译提示“命名空间“System.Web”中不存在类型或命名空间名称“Services”(是缺少程序集引用吗?)”,只需在解决方案资源管理器中添加对System.Web.Services的程序集引用即可。

2.)不建议调用

public static object InvokeAndCallWebService(string url, string methodname, object[] args)

即不指定类名,让程序由URL中分析出类名,因为不是所有服务的类名都放在URL的最后一个‘/’和‘.’中间的。

3.)@namespace不一定要取"EnterpriseServerBase.WebService.DynamicWebCalling",从我的实验中,取任意@namespace,甚至@namespace是空串都能够正常运行。

4.)网上有人说用这种方法调用Java写的Webservice时有问题,说是异常提示报的是无法获得相应空间里的类,有人说跟Java不要命名空间有关。我特意请同学帮我做一个java 的webservice(因为我不会java),实验证明这种方法并没有什么问题,我猜测报异常可能是因为没有指定类名,而是代码根据url分析类名,或者有可能是服务返回类型是一些复杂类型的值,建议返回类型最好是string或int之类的。

5.)在这种方法中url、命名空间、类名、函数名都是字符串,可以根据需要进行赋值。

3.调用

注意到上面实现的InvokeAndCallWebService是个静态函数,所以想利用WebServiceHelper调用Webservice方法如下。

            string url = "http://192.168.0.113/NM2SMARTB/INM2SmartSoap11Binding.asmx";
            string[] args = new string[1];
            args[0] = "hello";
            object result = webhelp.WebServiceHelper.InvokeAndCallWebService(url, "Nm2Smart", "getDevices", args);

4.变化

        上面的WebServiceHelper利用静态方法实现动态调用WebService,但是仍存在一个问题,就是每次函数InvokeAndCallWebService都要重新获取服务、生成代理等一系列过程,这样子的效率很低。所以可以对WebServiceHelper稍作修改,在服务没更改的的时候,只生成一次代理,可以多次调用其中的函数。大部分代码仍和上面一样。只是将服务实例化代码和调用分开,将InvokeAndCallWebService中的局部变量instance和@class变为类成员变量。如此只要声明一个WebServiceHelper对象,就可以只生成一次代理,多次调用函数,直到必要的时候再重新生成代理实例。当然此时函数已不是静态函数。
namespace webhelp
{
    using System;
    using System.Net;
    using System.IO;
    using System.CodeDom;
    using Microsoft.CSharp;
    using System.CodeDom.Compiler;
    using System.Web.Services.Description;
    using System.Web.Services.Protocols;
    public class WebServiceHelper
    {
 #region InvokeWebService
        object instance;//将原来函数内的局部变量变为类成员
        Type @class;//将原来函数内的局部变量变为类成员

        public void InvokeWebService(string url,/* string @namespace,*/ string classname)
        {
            string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling";
            if ((classname == null) || (classname == ""))
            {
                classname = WebServiceHelper.GetWsClassName(url);
            }

            try
            {
                //获取WSDL   
                WebClient webClient = new WebClient();
                Stream stream = webClient.OpenRead(url + "?WSDL");
                ServiceDescription description = ServiceDescription.Read(stream);
                ServiceDescriptionImporter descriptionImporter = new ServiceDescriptionImporter();
                descriptionImporter.AddServiceDescription(description, "", "");
                CodeNamespace codeNamespace = new CodeNamespace(@namespace);

                //生成客户端代理类代码   
                CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
                codeCompileUnit.Namespaces.Add(codeNamespace);
                descriptionImporter.Import(codeNamespace, codeCompileUnit);
                CSharpCodeProvider codeProvider = new CSharpCodeProvider();

                //设定编译参数   
                CompilerParameters compilerParameters = new CompilerParameters();
                compilerParameters.GenerateExecutable = false;
                compilerParameters.GenerateInMemory = true;
                compilerParameters.ReferencedAssemblies.Add("System.dll");
                compilerParameters.ReferencedAssemblies.Add("System.XML.dll");
                compilerParameters.ReferencedAssemblies.Add("System.Web.Services.dll");
                compilerParameters.ReferencedAssemblies.Add("System.Data.dll");

                //编译代理类   
                CompilerResults codeResult = codeProvider.CompileAssemblyFromDom(compilerParameters, codeCompileUnit);
                if (true == codeResult.Errors.HasErrors)
                {
                    System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
                    foreach (System.CodeDom.Compiler.CompilerError compileError in codeResult.Errors)
                    {
                        stringBuilder.Append(compileError.ToString());
                        stringBuilder.Append(System.Environment.NewLine);
                    }
                    throw new Exception(stringBuilder.ToString());
                }

                //生成代理实例  
                System.Reflection.Assembly assembly = codeResult.CompiledAssembly;
                @class = assembly.GetType(@namespace + "." + classname, true, true);
                instance = Activator.CreateInstance(@class);
                // return instance;                
            }
            catch (Exception ex)
            {
                throw new Exception(ex.InnerException.Message, new Exception(ex.InnerException.StackTrace));
            }
        }
        public object CallService(string methodname, object[] args)//调用方法与生成代理实例分开
        {
            try
            {
                System.Reflection.MethodInfo methorInfo = @class.GetMethod(methodname);
                return methorInfo.Invoke(instance, args);
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

        #endregion
    }
}

5.疑问

        作为一个新手,虽然知道动态调用的方法,但是其中一些东西还不是很了解,就像某老师说的“知其然不知其所以然”,希望能够有热心朋友帮我解答。比如@namespace是指什么的命名空间?我的想法是,这应该是指生成代理类所在的命名空间,但是如果我多次创建同一个代理,那不是在同一命名空间中存在多个同名类?却没有报错。或是我故意指定@namespace为webhelp,并在webhelp中定义一个同名的类,程序也是正常的。这里这个命名空间的作用是什么呢?即使指定命名空间为空字符串,仍是没有问题的。

C# 动态调用WebService <br /> <br />在C#程序中,若要调用WebService,一般是采用"添加Web引用"的方式来实现的。但如果此WebService的URL是在程序运行过程中才能获得的,那怎么办呢?那就必须是"动态"调用这个WebService了。<br /> <br />网上有不少关于这方面的例子,总结了一下,主要有两种:(1)每次都动态调用,(2)将WebService生成为一个本地的DLL,生成客户端的实例。<br /> <br />第一种方法:<br />我把它放到一个叫WebServiceHelper. 阅读详情

相关推荐

C#调用WebService服务(动态调用)

1 创建WebService using System; using System.Web.Services; namespace WebService1 { /// /// Service1 的摘要说明 /// [WebService(Namespace = "http://tempuri.org/", Description="测试服务")]

达拉斯母牛 2万+

C#动态webservice调用接口

C#动态webservice调用接口 using System; using System.Collections; using System.IO; using System.Net; using System.Text; using System.Xml; using System.Xml.Serialization; namespace Hishop.Plugins { /// /// 利用WebRequest/WebResponse进行WebService调用的类 /// public class WebServiceCall

C# 动态调用WebService实战技巧

本章深入讲解了如何在C#动态创建WebService客户端,并通过反射机制调用Web服务方法。从WSDL解析、动态编译到反射调用,每一步都进行了详细的代码实现和逻辑分析。此外,我们还封装了一个完整的动态调用工具类,并在多线程环境下进行了测试验证。通过本章内容,开发者可以掌握动态调用的核心技术,为构建灵活、可扩展的分布式系统打下坚实基础。当参数为自定义类(如User)时,需要确保该类在客户端与服务端具有相同的结构,以便正确序列化和反序列化。set;set;代码分析:使用。

weixin_35649491的博客 1245

C#调用WebService实例和开发(wsdl)

C#调用WebService实例和开发,对于初学者来说,在vs2012环境中,大家有可能不知道Web References文件夹是如何来的,它是通过右击项目,选择其中的”添加服务引用“。

C#调用 webservice 的三种方法总结

【0】如果不是为了维护老项目 ,左转grpc了解一下 【1】直接添加服务引用,然后调用相关方法。 【2】使用 HttpPost 请求调用 WebService public class WebServiceDemo : System.Web.Services.WebService { [WebMethod] public string HelloWorld() { return "Hello World"; }

欢迎指错||纠正||建议||水评+点赞&&评论&&关注&&转发 1万+

C# 动态获取webservice的接口

【代码】C# 动态获取webservice的接口。

ilikehigame的专栏 1111

C# 动态调用Webservice

通常我们在程序vb.net教程中需要c#教程调用WebService时,都是python基础教程通过“添加Web引用”,让VS.NET环境来java基础教程为我们生成服务sql教程代理,然后调用对应的Web服务。这样是使工作简单了,但是却和提供Web服务的URL、方法名、参数绑定在一起了,这是VS.NET自动为我们生成Web服务代理的限制。如果哪一天发布Web服务的URL改变了,则我们需要重新让VS.NET生成代理,并重新编译。在某些情况下,这可能是不能忍受的,我们需要动态调用WebService的能力。比

chinaherolts2008的博客 816

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

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

C# WebService动态调用

C# WebService动态调用 前言   站在开发者的角度,WebService 技术确实是不再“时髦”。甚至很多人会说,我们不再用它。当然,为了使软件可以更简洁,更有层次,更易于实现缓存等机制,我是非常建议将 SOAP 转为 RESTful 架构风格的。但到目前为止,WebService 在一些Public Institution 中使用还是十分广泛的。   这...

184

C#动态调用WebService的完整指南

WebService作为实现应用程序间通信的一种基于Web的技术,它允许应用程序通过互联网进行跨平台的通信。它通常使用基于XML的SOAP协议,构建在HTTP之上,提供了一种标准的方法来处理网络间的请求与响应。其主要特点包括语言无关性、平台独立性和松耦合性。WebService允许不同系统和编程语言的应用程序进行数据交换和功能调用,从而实现企业应用集成(EAI)或业务流程集成(BPI)。了解WebService通信协议的基本原理,对于从事IT行业的专业人员来说是必备的基础知识。

weixin_42583683的博客 599

C#动态调用webservice

C#动态调用webservice 方法一: Web Service内容没有变,只是换了各地方。比如从localhost:8080/a.asmx换到了localhost:8090/a.asmx。如此一来你不必重新修改Web Reference只需要在使用WebMethod时 WebS.A a = new WebS.A(); a.Url="http://localhost:8090/a.

.net的专栏 663

C#动态调用webServices(详细)

首先我们要创建好webServices项目文件可以是一个项目也可以是一个单独的文件放在其他项目中。 创建webServices文件的头部,引用依赖将AJAX调用此web服务取消注释。 /// <summary> /// AddApplyOnline 的摘要说明 /// </summary> [WebService(Namespace = "http://192.168.1.48:3030/AddApplyOnline.asmx/AddApplyOnlin

Y2210151431的博客 4650

C#调用WebService接口的三种方式

WebService服务端会提供wsdl文件,客户端通过该文件生成.cs文件以及生成.dllPS:注意若是服务端只提供了URL,那可以通过在URL后面加上“?wsdl”在浏览器上访问,复制页面的代码内容,粘贴到文本文件,将文件后缀改为“wsdl”,即可得到wsdl文件。通过URL或wsdl文件都可生成.cs文件。

weixin_38812575的博客 8576

C#调用WebService的方法

【代码】C#调用WebService的方法。

qq_38151300的博客 3870

C# 使用Get,Post,Soap方式调用WebService

using System; using System.Web; using System.Xml; using System.Collections; using System.Net; using System.Text; using System.IO; using System.Xml.Serialization; //By huangz 2008-3-19 /// /// 利用W

无名剑 3778
上一篇: VS写C#的小技巧
下一篇: C#将字符串转换成XML格式
aleyuan
博客等级 码龄17年 34粉丝 20原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值