• http动态调用webserive


       前言

       传统方式调用WebService是直接引用服务,生成客户端代理类类,这种方式将ws进行了再次封装,并以代理的方式进行调用,这种方式的优点是简单,方便。

       但是此种方式不足的地方是,当对方ws接口变更时,这边引用的服务同时也需要编译并部署,或者我调用方这边想动态指定不同服务地址时,此方式就不太适应这种场景了。

        有一种方式是动态调用ws的方式。就是通过ws的服务描述获取生成客户端的代理并动态编译,通过反射生成实例对象,并完成ws的调用。大致代码如下

     1 /// <summary> 
     2         /// 动态调用WebService 
     3         /// </summary> 
     4         /// <param name="url">WebService地址</param> 
     5         /// <param name="classname">类名</param> 
     6         /// <param name="methodname">方法名(模块名)</param> 
     7         /// <param name="args">参数列表</param> 
     8         /// <returns>object</returns> 
     9         public static object InvokeWebService(string url, string classname, string methodname, object[] args)
    10         {
    11             string @namespace = "ServiceBase.WebService.DynamicWebLoad";
    12             if (classname == null || classname == "")
    13             {
    14                 classname = WebServiceHelper.GetClassName(url);
    15             }
    16             //获取服务描述语言(WSDL) 
    17             WebClient wc = new WebClient();
    18             Stream stream = wc.OpenRead(url + "?WSDL");
    19             ServiceDescription sd = ServiceDescription.Read(stream);
    20             ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
    21             sdi.AddServiceDescription(sd, "", "");
    22             CodeNamespace cn = new CodeNamespace(@namespace);
    23             //生成客户端代理类代码 
    24             CodeCompileUnit ccu = new CodeCompileUnit();
    25             ccu.Namespaces.Add(cn);
    26             sdi.Import(cn, ccu);
    27             CSharpCodeProvider csc = new CSharpCodeProvider();
    28             ICodeCompiler icc = csc.CreateCompiler();
    29             //设定编译器的参数 
    30             CompilerParameters cplist = new CompilerParameters();
    31             cplist.GenerateExecutable = false;
    32             cplist.GenerateInMemory = true;
    33             cplist.ReferencedAssemblies.Add("System.dll");
    34             cplist.ReferencedAssemblies.Add("System.XML.dll");
    35             cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
    36             cplist.ReferencedAssemblies.Add("System.Data.dll");
    37             //编译代理类 
    38             CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);
    39             if (true == cr.Errors.HasErrors)
    40             {
    41                 System.Text.StringBuilder sb = new StringBuilder();
    42                 foreach (CompilerError ce in cr.Errors)
    43                 {
    44                     sb.Append(ce.ToString());
    45                     sb.Append(System.Environment.NewLine);
    46                 }
    47                 throw new Exception(sb.ToString());
    48             }
    49             //生成代理实例,并调用方法 
    50             System.Reflection.Assembly assembly = cr.CompiledAssembly;
    51             Type t = assembly.GetType(@namespace + "." + classname, true, true);
    52             object obj = Activator.CreateInstance(t);
    53             System.Reflection.MethodInfo mi = t.GetMethod(methodname);
    54             return mi.Invoke(obj, args);
    55         }
    56 
    57         private static string GetClassName(string url)
    58         {
    59             string[] parts = url.Split('/');
    60             string[] pps = parts[parts.Length - 1].Split('.');
    61             return pps[0];
    62         }
    View Code

       但是这种方式,最明显的方式就是性能较差,每次都要重新生成反射调用,所以一般情况不用它。

         那还有别的方法吗?

         那我就来说说今天在工作中用到的方法。

        soap请求

        首先需要知道传统的调用方式的通行协议是关键,ws底层也是走的http方式,只是加了多加了soap协议在里面,那怎么拿到它的交互协议呢,有一个神器叫fiddler,它可以监测http请求和响应信息。有了它,就有了协议了,剩下就是拼装协议了。

        仔细观察协议后 发现它的交互结构如下

    POST /WebServiceTest/Service1.asmx HTTP/1.1
    Host: localhost
    Content-Type: text/xml; charset=utf-8
    Content-Length: length
    SOAPAction: "http://tempuri.org/HelloWorld"
     
    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <soap:Body>
        <HelloWorld xmlns="http://tempuri.org/">
          <StudentName>string</StudentName>
          <PassWord>string</PassWord>
        </HelloWorld>
      </soap:Body>
    </soap:Envelope>
    SOAPAction这个就是表示请求的具体方法,在请求流中,在写入上面的基于xml的soap协议,接下来就可以发起请求了,顺利的话就能拿到响应了。

    做事有根有据,仔细并专注,不经意间,就能成功不远了。
  • 相关阅读:
    解决Odoo出现的Unable to send email, please configure the sender's email address or alias.
    Odoo误删除服务产品造成的错误解决办法
    Linux面试题汇总答案
    win7下安装openpyxl
    在Win7下使用sphinx-build建立开源软件文档
    如何把一个excel工作薄中N个工作表复制到另一个工作薄中
    如何手动添加Windows服务和如何把一个服务删除
    创建用户角色时出现的500错误问题解决方法
    odoo注销后在登录时的用户名和密码
    XenServer6.2详细安装步骤
  • 原文地址:https://www.cnblogs.com/JaggerMan/p/4893253.html
Copyright © 2020-2023  润新知