一、什么是WebService?

这里就不再赘述了,想要了解的====》传送门

二、为什么要动态调用WebService接口?

一般在C#开发中调用webService服务中的接口都是通过引用过来就行调用的,步骤如下:

1.找到引用,右击添加服务引用,找到高级,添加web引用,添加之后就可以直接调用里面的方法。

以上这种方法是最简单粗暴的一种方式。当然在开发中总是不那么如意,以上方式是在本机直接可以访问服务的地址,假如在本机不能直接访问WebService,那么就会有些蛋疼。

这种方式就不可取了,那么有什么方式可以不直接访问就可以开发呢?这就要使用动态调用的方式进行调用了。接下来就是如何动态调用WebService了。

三、动态调用WebService的几种方式

方式一:

随便百度一下就可以找到的一种,接下了的代码来源于百度找到的并性能进行优化升级过。

  1. public static class CommonServiceHelper
  2. {
  3. /// <summary>
  4. /// 静态缓存字典,速度提升至8倍
  5. /// </summary>
  6. private static Dictionary<string, object> _webServiceConfig = new Dictionary<string, object>();
  7.  
  8. //获取WSDL
  9. private static readonly WebClient wc = new WebClient();
  10.  
  11. /// < summary>
  12. /// 动态调用web服务
  13. /// </summary>
  14. /// < param name="url">WSDL服务地址</param>
  15. /// < param name="classname">类名</param>
  16. /// < param name="methodname">方法名</param>
  17. /// < param name="args">参数</param>
  18. /// < returns></returns>
  19. public static object InvokeWebService(this string url, string methodname, object[] args, string classname = "")
  20. {
  21. string key = $"{url}_{methodname}";//缓存Key唯一标识
  22. Type webService;
  23. if (!_webServiceConfig.ContainsKey(key))
  24. {
  25. string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling";
  26. //classname 一般自己指定 如果有些地址是http://www.webxml.com.cn/WebServices/WeatherWS?wsdl 就会调用失败
  27. if ((classname == null) || (classname == ""))
  28. {
  29. classname = GetWsClassName(url);
  30. }
  31. try
  32. {
  33. Stream stream = wc.OpenRead(url);
  34. ServiceDescription sd = ServiceDescription.Read(stream);
  35. ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
  36. sdi.AddServiceDescription(sd, "", "");
  37. CodeNamespace cn = new CodeNamespace(@namespace);
  38. CodeCompileUnit ccu = new CodeCompileUnit();
  39. ccu.Namespaces.Add(cn);
  40. sdi.Import(cn, ccu);
  41. CSharpCodeProvider icc = new CSharpCodeProvider();
  42. CompilerParameters cplist = new CompilerParameters
  43. {
  44. GenerateExecutable = false,
  45. GenerateInMemory = true
  46. };
  47. cplist.ReferencedAssemblies.Add("System.dll");
  48. cplist.ReferencedAssemblies.Add("System.XML.dll");
  49. cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
  50. cplist.ReferencedAssemblies.Add("System.Data.dll");
  51. CompilerResults compiler = icc.CompileAssemblyFromDom(cplist, ccu);
  52. icc.Dispose();
  53. if (compiler.Errors.HasErrors)
  54. {
  55. System.Text.StringBuilder sb = new System.Text.StringBuilder();
  56. foreach (CompilerError ce in compiler.Errors)
  57. {
  58. sb.Append(ce.ToString());
  59. sb.Append(Environment.NewLine);
  60. }
  61. throw new Exception(sb.ToString());
  62. }
  63. System.Reflection.Assembly assembly = compiler.CompiledAssembly;
  64. Type t = assembly.GetType(@namespace + "." + classname, true, true);
  65. webService = t;
  66. _webServiceConfig.Add(key, webService);//加入缓存
  67. }
  68. catch (Exception ex)
  69. {
  70. throw new Exception(ex.Message);
  71. }
  72. }
  73. else
  74. {
  75. webService = _webServiceConfig[key] as Type;//获取缓存的数据
  76. }
  77. if (webService != null)
  78. {
  79. object obj = Activator.CreateInstance(webService);
  80. System.Reflection.MethodInfo mi = webService.GetMethod(methodname);
  81. if (mi != null)
  82. {
  83. return mi.Invoke(obj, args);
  84. }
  85. throw new Exception($"找不到{methodname}这个方法,调用失败");
  86. }
  87. else
  88. {
  89. throw new Exception($"WebService 对象为空,调用失败");
  90. }
  91. }
  92.  
  93. /// <summary>
  94. /// 获取wsdl类名称
  95. /// </summary>
  96. /// <param name="wsUrl">wsdl地址</param>
  97. /// <returns></returns>
  98. private static string GetWsClassName(string wsUrl)
  99. {
  100. string[] parts = wsUrl.Split('/');
  101. string[] pps = parts[parts.Length - ].Split('.');//classname 一般自己指定 原因是因为在这里
  102. return pps[];
  103. }
  104. /// <summary>
  105. /// 清空缓存
  106. /// </summary>
  107. public static void ClearCache()
  108. {
  109. _webServiceConfig.Clear();
  110. }
  111. }

以上方法是第一种,这种方法不是万能的,因为方法是通过反射调用的,多个参数的时候顺序不能乱,方法名称不能写错,对于有些WebService是无法调用的。

方式二:

这种方式针对本机不能访问的WebService非常有效,参数啥的不容易搞混,跟C#直接添加引用之后调用方式一样。

C#添加引用的方式是通过对于WebService的xml进行解析并生成相关代码,根据原理可知,只要有WebService的xml就好办了。

对于本机不能访问的WebService,找个可以访问的环境,用浏览器进行访问,后面加上wsdl,例如:http://www.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl

然后进行访问,把页面另存为你可以找得到的地方。我这里直接存储到D盘

把这个xml文件丢到你本地随便一个可以访问的的站点下,这个xml文件要可以正常访问。(这个很重要)

接下来就要使用visual studio 开发人员命令工具,我这里是使用vs2019 ,前面几个版本的vs都可以

在开始菜单里面找到并打开

接下来使用命令生成代码。

命令如下:wsdl  你本地访问的那个xml地址全路径

我这里是放在端口81的站点下

生成的cs类文件跟通过web引用生成的cs文件是一样,这样就可以解决本机不能直接访问WebService不能调用方法的问题。

当然,想要可以执行其中的方法还需要把代码放到对应环境上才能执行。

四、总结

以上是使用两种方式动态调用WebService接口的方式,在实际开发中,遇到不能访问的,一般用第二种比较保险。

动态调用WebService接口的几种方式的更多相关文章

  1. C#动态调用WCF接口,两种方式任你选。

    写在前面 接触WCF还是它在最初诞生之处,一个分布式应用的巨作. 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项目时用到了WCF. 从这 ...

  2. Python调用API接口的几种方式 数据库 脚本

    Python调用API接口的几种方式 2018-01-08 gaoeb97nd... 转自 one_day_day... 修改 微信分享: 相信做过自动化运维的同学都用过API接口来完成某些动作.AP ...

  3. Python调用API接口的几种方式

    Python调用API接口的几种方式 相信做过自动化运维的同学都用过API接口来完成某些动作.API是一套成熟系统所必需的接口,可以被其他系统或脚本来调用,这也是自动化运维的必修课. 本文主要介绍py ...

  4. 动态调用webservice 接口

    1.url:http://localhost:8002/名称.asmx(asmx结尾) 2.需要引用的命名空间:System.Web.Services 3.调用代码: public class Dyn ...

  5. java调用CXF WebService接口的两种方式

    通过http://localhost:7002/card/services/HelloWorld?wsdl访问到xml如下,说明接口写对了. 2.静态调用 // 创建WebService客户端代理工厂 ...

  6. 【Java EE 学习 80 下】【调用WebService服务的四种方式】【WebService中的注解】

    不考虑第三方框架,如果只使用JDK提供的API,那么可以使用三种方式调用WebService服务:另外还可以使用Ajax调用WebService服务. 预备工作:开启WebService服务,使用jd ...

  7. c#动态调用WEBSERVICE接口

    C#动态webservice调用接口 1 using System; 2 using System.Collections; 3 using System.IO; 4 using System.Net ...

  8. java调用http接口的几种方式总结

    本文参考: https://blog.csdn.net/fightingXia/article/details/71775516 https://www.cnblogs.com/jeffen/p/69 ...

  9. SoapUI调用webservice实现的两种方式

    SoapUI用来做测试,已经是很多人做过的事情了,而且网上教程也很多.不过还是写下来,对比webservice协议与http协议脚本编写的不同. 首先测接口得有一个服务,刚好笔者所在项目做ESB集成. ...

随机推荐

  1. 对C++类的继承和派生的理解

    C++中的继承是类与类之间的关系,是一个很简单很直观的概念,与现实世界中的继承类似,例如儿子继承父亲的财产. 1.继承(Inheritance)可以理解为一个类从另一个类获取成员变量和成员函数的过程. ...

  2. requests库爬取豆瓣热门国产电视剧数据并保存到本地

    首先要做的就是去豆瓣网找对应的接口,这里就不赘述了,谷歌浏览器抓包即可,然后要做的就是分析返回的json数据的结构: https://movie.douban.com/j/search_subject ...

  3. python网络编程-socket套接字通信循环-粘包问题-struct模块-02

    前置知识 不同计算机程序之间数据的传输 应用程序中的数据都是从程序所在计算机内存中读取的. 内存中的数据是从硬盘读取或者网络传输过来的 不同计算机程序数据传输需要经过七层协议物理连接介质才能到达目标程 ...

  4. API 网关性能比较:NGINX vs. ZUUL vs. Spring Cloud Gateway vs. Linkerd

    前几天拜读了 OpsGenie 公司(一家致力于 Dev & Ops 的公司)的资深工程师 Turgay Çelik 博士写的一篇文章(链接在文末),文中介绍了他们最初也是采用 Nginx 作 ...

  5. 常用的TCP/UDP端口

    已知的TCP/UDP端口可以在wikipedia上找到: List of TCP and UDP port numbers, 太多了,按组列举了最常用的,如下: FTP:21SSH:22Telnet: ...

  6. hive各种报错

    搭建了 CDH6.1.0环境 新加入一台机器都hive但是报错 javax.jdo.JDODataStoreException: Required table missing : "`VER ...

  7. 给Tomcat打开远程debug端口

    >cd apache-tomcat-8.5.24 >cd conf >vim catalina.sh 在文件开始处添加: CATALINA_OPTS="-server -X ...

  8. Delphi 适合于文本文件的基本操作

  9. strings、strconv:让你高效的处理字符串

    strings包 strings.HasPrefix(s, prefix string) bool 判断字符串s是否以prefix开头.类似于python中的startswith. package m ...

  10. deep_learning_Function_tf.add()、tf.subtract()、tf.multiply()、tf.div()

    tf.add().tf.subtract().tf.multiply().tf.div()函数介绍和示例 1. tf.add() 释义:加法操作 示例: x = tf.constant(2, dtyp ...