C#动态调用web服务 远程调用技术WebService
一、课程介绍
一位伟大的讲师曾经说过一句话:事物存在即合理!意思就是说:任何存在的事物都有其存在的原因,存在的一切事物都可以找到其存在的理由,我们应当把焦点放在因果关联的本质上。所以在本次分享课开课之前,我们要“约法三章”不谈论以下几个比较“严肃”和“敏感”的话题:WebService已经过时了啦,学习它干什么用啊!为什么要用WebService,而不用基于当前流行的RestFul ASP.NET WebAPI ? 对于上面的问题阿笨的回答很简单:因为它就是它,不一样烟火的WebService!
本次分享课您将学习到以下干货知识点:
1)、WebService技术调用原理图。
2)、C# WebService常用的几种调用方式。
3)、C# WebService调试小技巧和开发必备工具分享。
4)、实战演练之如何通过优雅的方式进行WebService调用。 优不优雅,你看了就知道了,我们尽可能的Write Less Do More !(强烈推荐)
在此插播一条硬广告:下一堂分享课程阿笨计划将给大家带来《C#远程调用技术WebService葵花宝典》,课程的重点将给大家分享一下“C# WebService两种不同引用使用方式”,“WebService如何使用异步调用”以及“关于C# WebService如何让客户端以安全的方式进行调用目前常用几种的解决方案”等等。阿笨尽量给大家带来一些干货分享!
如果您对本次分享课感兴趣的话,那么请跟着阿笨一起学习吧。废话不多说,直接上干货,我们不生产干货,我们只是干货的搬运工。
hi大家好,我的名字叫WebService!
二、概念名称含义解释
2.1、什么是远程调用技术(简称:RPC技术)?
一个系统远程调用另一个系统的服务,来获取远程系统的业务数据。
2.2、为什么使用RPC技术?
基于安全性的考虑,一般企业不会开放自己的数据库,只能使用远程调用技术。
2.3、什么是SOAP?
SOAP:(Simple Object Access Protocol)简单对象存取协议。SOAP最早是针对RPC的一种解决方案;SOAP是XML文档形式的调用方法的规范。
2.4、什么是WebService?
WebService是一种使用HTTP传输的SOAP协议的远程调用技术。
2.5、WebService采用的是什么通信协议?
WebService 采用的的基本通信协议是SOAP ,它是在分散或分布式环境中交换信息,它基于XML的协议,通过SOAP协议可以实现不同项目、不同地点、甚至异地调用应用程序。
2.6、为什么说WebService是跨平台的?
实际上,WebService 的主要目标是跨平台的可互操作性。为了达到这一目标,WebService 完全基于XML (可扩展标记语言)、XSD (XMLSchema )等独立于平台、独立于软件供应商的标准,是创建可互操作的、分布式应用程序的新平台。
2.7、WebService实现包含那三要素?
WSDL作用:webservice服务端的使用说明书。(Web Service Description Language)
SOAP作用:规范XML标签。
UDDI:提供webservice服务端的搜索和注册功能。
2.8、WebService有哪些优势?
1)、可操作的的分布式应用程序。
可以实现不同应用程序和在不同系统平台上开发出来的应用程序之间通信。
2)、普遍性、使用HTTP和XML进行通信。
任何支持HTTP和XML 技术的设备都可以拥有和访问Web Service,不同平台不同开发语言照样可以调用我们发布的Web Service。
3)、Web Service 甚至可以穿越防火墙,真正的自由通信。
一般要访问的Web服务器以及要访问的Web Service的客户端很可能位于防火墙后面,都默认关闭其它端口而开发HTTP端口,而Web service 正是基于HTTP的,所以它可以穿越防火墙.
4)、异构平台之间的互通性。
Web Service 最大的优势是提供了异构平台的无缝街接技术手段。由于不同的用户使用不同的硬件平台,不同的操作平台,不同的操作系统,不同的软件,不同的 协议通信,这就产生了互相通信的需求。 Web Service 使任何两个应用程序,只要能读写XML,那么就能互相通信。 通过 SOAP 协议实现异地调用。
小结:
阿笨用通俗一点语言解释就是在当前C#、JAVA、PHP等语言都可以使用标准的WebService技术实现不同语言的应用程序之间进行互相通信,即互相调用。
三、WebService技术调用原理图
WebService工作原理图一
WebService工作原理图二
3.1、Webservice是如何实现远程调用?三要素在webservice的作用?
(1)Webservice原理:webservice是一种使用http传输的SOAP协议的数据的远程调用技术。
(2) WSDL作用:webservice服务端的使用说明书。(Web Service Description Language)
(3)SOAP作用:规范XML标签。
(4) UDDI:提供webservice服务端的搜索和注册功能。
3.2、WebService关键原理说明:
服务者:发布者需要部署Webservice服务应用程序。
调用者:客户端需要参考webservice服务端的使用说明书(WSDL)进行调用。
四、C# WebService常用的几种调用方式
4.1、C#通过Dynamic动态调用WebService。
其实与手工创建添加引用步骤一样,只是在这里把手动变成了自动而已,动态生成代理类,利用反射动态调用了方法。详细请参考:[C#通过Dynamic动态调用WebService.pdf]文档。
4.2、C#通过模拟HTTP请求协议Get、POST方式进行调用WebService。(根据个人项目情况使用)
详细请参考:[C#通过模拟HTTP请求协议Get、POST方式进行调用WebService.pdf]文档。
4.3、通过手动生成客户端WSDL代理类进行调用。(根据个人项目情况使用)
采用微软给我们提供的wsdl.exe工具生成wsdl本地代理类。
4、通过SOAP协议手动引用方式进行调用。(微软强烈推荐)
五、C# WebService调试小技巧和开发必备工具分享
5.1、C# 如何调试WebService服务以及调试远程Web服务。
详细请参考[C# WebService如何远程调试.pdf]
5.2、Webservice调试利器
1、微软提供的.NET WebService Studio
下载地址:http://webservicestudio.codeplex.com/
2、Storm (推荐)
下载地址:http://storm.codeplex.com/ ,顺便提及下该工具还有一个它的“同胞兄弟”叫 WCF Storm 哦。
3、soapui(强烈推荐)
六、实战演练之如何通过优雅的方式进行WebService调用
统一入口获取指定T类型的WebService服务实例
客户端调用者将采用统一入口进行访问
--------------------------------
public class DynamicWebServices
{
static SortedList<string, Type> _typeList = new SortedList<string, Type>();
#region InvokeWebService
static string GetCacheKey(string url, string className)
{
return url.ToLower() + className;
}
static Type GetTypeFromCache(string url, string className)
{
string key = GetCacheKey(url, className);
foreach (KeyValuePair<string, Type> pair in _typeList)
{
if (key == pair.Key)
{
return pair.Value;
}
}
return null;
}
static Type GetTypeFromWebService(string url, string className)
{
string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling";
if ((className == null) || (className == ""))
{
className = GetWsClassName(url);
}
//http://blog.csdn.net/lzy_1515
//获取WSDL
WebClient wc = new WebClient();
Stream stream = wc.OpenRead(url + "?WSDL");
ServiceDescription sd = ServiceDescription.Read(stream);
ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
sdi.AddServiceDescription(sd, "", "");
CodeNamespace cn = new CodeNamespace(@namespace);
//生成客户端代理类代码
CodeCompileUnit ccu = new CodeCompileUnit();
ccu.Namespaces.Add(cn);
sdi.Import(cn, ccu);
CSharpCodeProvider csc = new CSharpCodeProvider();
ICodeCompiler icc = csc.CreateCompiler();
//设定编译参数
CompilerParameters cplist = new CompilerParameters();
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");
//编译代理类
CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);
if (true == cr.Errors.HasErrors)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (System.CodeDom.Compiler.CompilerError ce in cr.Errors)
{
sb.Append(ce.ToString());
sb.Append(System.Environment.NewLine);
}
throw new Exception(sb.ToString());
}
//生成代理实例,并调用方法
System.Reflection.Assembly assembly = cr.CompiledAssembly;
Type t = assembly.GetType(@namespace + "." + className, true, true);
return t;
}
//动态调用web服务
public static object InvokeWebService(string url, string methodName, object[] args)
{
return InvokeWebService(url, null, methodName, args);
}
public static object InvokeWebService(string url, string className, string methodName, object[] args)
{
try
{
Type t = GetTypeFromCache(url, className);
if (t == null)
{
t = GetTypeFromWebService(url, className);
//添加到缓冲中
string key = GetCacheKey(url, className);
_typeList.Add(key, t);
}
object obj = Activator.CreateInstance(t);
MethodInfo mi = t.GetMethod(methodName);
return mi.Invoke(obj, 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
// http://blog.csdn.net/lzy_1515
}
private Type[] CompileCode(CodeCompileUnit ccu)
{
CodeDomProvider cprovider = new Microsoft.CSharp.CSharpCodeProvider();
CompilerParameters cp = new CompilerParameters();
string[] assemblies = this.GetReferencedAssemblies();
cp.ReferencedAssemblies.AddRange(assemblies);
cp.ReferencedAssemblies.AddRange(new string[] { "System.dll", "System.Xml.dll", "System.Windows.Forms.dll", "System.Data.dll", "System.Drawing.dll", "System.Runtime.Serialization.dll", "System.Core.dll" });
CompilerResults cr = cprovider.CompileAssemblyFromDom(cp, ccu);
if (cr.Errors.Count > 0)
{
string[] ss = (from CompilerError e in cr.Errors select e.ErrorText).ToArray();
throw new Exception(string.Join("\n", ss));
}
else
return cr.CompiledAssembly.GetTypes();
}
其他参考