• C# 调用Java的WebService的3种方式


    C# 调用WebService的3种方式 :直接调用、根据wsdl生成webservice的.cs文件及生成dll调用、动态调用

     

     关于soapheader调用,可以参考

    C#调用Java的WebService添加SOAPHeader验证

    1.问题描述

    调用的Java的webservice

    string Invoke(string func, string reqXml)

     使用C#直接调用一直报错。

    webservice提供方有说明如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    身份验证采用对SOAP身份认证(用户名/密码验证/序列号)的方式部署,设定用户名和密码由系统配置,所有文本内容编码选择UTF-8编码规范
    <?xml version='1.0' encoding='utf-8'?>
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header>
    <vc:Authentication xmlns: vc ="http://ant.com">
    <vc:Username>[系统配置] </vc:Username>
    <vc:Password>[系统配置]</vc:Password>
    <vc:SerialNo>[系统配置]</vc:SerialNo >
    </vc:Authentication>
    </soapenv:Header>
    <soapenv:Body>
    </soapenv:Body>
    </soapenv:Envelope>

    相信就是soapenv:Header这里的问题了,C# 没soapenv:Header这些东西的

    网上查了好多类似下面的

    https://www.cnblogs.com/o2ds/p/4093413.html

    C#访问Java的WebService添加SOAPHeader验证的问题

    都没有用

    后来尝试sopui及xmlspy创建soap,直接发送xml,终于试出来了,然后C#使用http post调用webservice,成功了。

    2.问题解决1

    C#拼接的需要http post的soap字符串如下

    </SOAP-ENV:Header> 照搬给的文档里的字符串
    <SOAP-ENV:Body> 为调用函数,string Invoke(string func, string reqXml) 函数名Invoke,两个参数,自行理解吧

    注意:里面的 换行标志都要保留,不然都是报错

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    string soap = "<?xml version="1.0" encoding="utf-8"?> " +
                   "<SOAP-ENV:Envelope " +
                   "xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" " +
                   "xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" " +
                   "xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" " +
                   "xmlns:xsd="http://www.w3.org/2001/XMLSchema"> " +
                   "<SOAP-ENV:Header> " +
                       "<vc:Authentication " +
                           "xmlns:vc="http://ant.com"> " +
                           "<vc:Username>xx</vc:Username> " +
                           "<vc:Password>xxx</vc:Password> " +
                           "<vc:SerialNo>xxxx</vc:SerialNo> " +
                       "</vc:Authentication> " +
                   "</SOAP-ENV:Header> " +
                   "<SOAP-ENV:Body> " +
                       "<m:Invoke " +
                           "xmlns:m="http://tempuri.org/"> " +
                           "<m:func>" + jkid + "</m:func> " +
                           "<m:reqXml>" + HttpUtility.HtmlEncode(xml) + "</m:reqXml> " +
                       "</m:Invoke> " +
                   "</SOAP-ENV:Body> " +
                   "</SOAP-ENV:Envelope>";

      然后发送,随便找个http post的代码就行了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public static string GetSOAPReSource(string url, string datastr)
           {
               try
               {
                   //request
                   Uri uri = new Uri(url);
                   WebRequest webRequest = WebRequest.Create(uri);
                   webRequest.ContentType = "text/xml; charset=utf-8";
     
                   webRequest.Method = "POST";
                   using (Stream requestStream = webRequest.GetRequestStream())
                   {
                       byte[] paramBytes = Encoding.UTF8.GetBytes(datastr.ToString());
                       requestStream.Write(paramBytes, 0, paramBytes.Length);
                   }
                   //response
                   WebResponse webResponse = webRequest.GetResponse();
                   using (StreamReader myStreamReader = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8))
                   {
                       string result = "";
                       return result = myStreamReader.ReadToEnd();
                   }
               }
               catch (Exception ex)
               {
                   throw ex;
               }
           }

      

    3.问题解决2

    发现还是报错,http 500错误,和之前不一样,但依然不对

    研究webservice的wsdl发现了问题

    调用时加上

    1
    <strong>webRequest.Headers.Add("SOAPAction""http://tempuri.org/IAjsjService/Invoke");<br><br></strong>终于成功了
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    public static string GetSOAPReSource(string url, string datastr)
           {
               try
               {
                   //request
                   Uri uri = new Uri(url);
                   WebRequest webRequest = WebRequest.Create(uri);
                   webRequest.ContentType = "text/xml; charset=utf-8";
                   webRequest.Headers.Add("SOAPAction""http://tempuri.org/IAjsjService/Invoke");
     
                   webRequest.Method = "POST";
                   using (Stream requestStream = webRequest.GetRequestStream())
                   {
                       byte[] paramBytes = Encoding.UTF8.GetBytes(datastr.ToString());
                       requestStream.Write(paramBytes, 0, paramBytes.Length);
                   }
                   //response
                   WebResponse webResponse = webRequest.GetResponse();
                   using (StreamReader myStreamReader = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8))
                   {
                       string result = "";
                       return result = myStreamReader.ReadToEnd();
                   }
               }
               catch (Exception ex)
               {
                   throw ex;
               }
           }

      

    其他调用webservice的方式:

    上一篇链接如上,更像是 Net下采用GET/POST/SOAP方式动态调用WebService的简易灵活方法(C#) 来处理xml,解决复杂的认证

    又遇到一家

    复制代码
    身份验证采用对SOAP身份认证(用户名/密码验证/序列号)的方式部署,设定用户名和密码由系统配置,所有文本内容编码选择UTF-8编码规范
    <?xml version='1.0' encoding='utf-8'?>
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header>
    <vc:Authentication xmlns: vc ="http://ant.com">
    <vc:Username>[系统配置] </vc:Username>
    <vc:Password>[系统配置]</vc:Password>
    <vc:SerialNo>[系统配置]</vc:SerialNo >
    </vc:Authentication>
    </soapenv:Header>
    <soapenv:Body>
    </soapenv:Body>
    </soapenv:Envelope> 
    复制代码

    wsdl的xml如下

    <?xml version="1.0" encoding="utf-8"?><wsdl:definitions name="AjsjService" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://tempuri.org/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"><wsdl:types><xsd:schema targetNamespace="http://tempuri.org/Imports"><xsd:import schemaLocation="vehcheck0.xml" namespace="http://tempuri.org/"/><xsd:import schemaLocation="vehcheck1.xml" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/></xsd:schema></wsdl:types><wsdl:message name="IAjsjService_Invoke_InputMessage"><wsdl:part name="parameters" element="tns:Invoke"/></wsdl:message><wsdl:message name="IAjsjService_Invoke_OutputMessage"><wsdl:part name="parameters" element="tns:InvokeResponse"/></wsdl:message><wsdl:message name="IAjsjService_TrffpnCall_InputMessage"><wsdl:part name="parameters" element="tns:TrffpnCall"/></wsdl:message><wsdl:message name="IAjsjService_TrffpnCall_OutputMessage"><wsdl:part name="parameters" element="tns:TrffpnCallResponse"/></wsdl:message><wsdl:portType name="IAjsjService"><wsdl:operation name="Invoke"><wsdl:input wsaw:Action="http://tempuri.org/IAjsjService/Invoke" message="tns:IAjsjService_Invoke_InputMessage"/><wsdl:output wsaw:Action="http://tempuri.org/IAjsjService/InvokeResponse" message="tns:IAjsjService_Invoke_OutputMessage"/></wsdl:operation><wsdl:operation name="TrffpnCall"><wsdl:input wsaw:Action="http://tempuri.org/IAjsjService/TrffpnCall" message="tns:IAjsjService_TrffpnCall_InputMessage"/><wsdl:output wsaw:Action="http://tempuri.org/IAjsjService/TrffpnCallResponse" message="tns:IAjsjService_TrffpnCall_OutputMessage"/></wsdl:operation></wsdl:portType><wsdl:binding name="BasicHttpBinding_IAjsjService" type="tns:IAjsjService"><soap:binding transport="http://schemas.xmlsoap.org/soap/http"/><wsdl:operation name="Invoke"><soap:operation soapAction="http://tempuri.org/IAjsjService/Invoke" style="document"/><wsdl:input><soap:body use="literal"/></wsdl:input><wsdl:output><soap:body use="literal"/></wsdl:output></wsdl:operation><wsdl:operation name="TrffpnCall"><soap:operation soapAction="http://tempuri.org/IAjsjService/TrffpnCall" style="document"/><wsdl:input><soap:body use="literal"/></wsdl:input><wsdl:output><soap:body use="literal"/></wsdl:output></wsdl:operation></wsdl:binding><wsdl:service name="AjsjService"><wsdl:port name="BasicHttpBinding_IAjsjService" binding="tns:BasicHttpBinding_IAjsjService"><soap:address location="http://ip:8000/v"/></wsdl:port></wsdl:service></wsdl:definitions>

    使用添加服务引用加到项目里

    不要用高级那里的添加web引用添加,不然后面没法做

    生成的Reference.cs如下

    复制代码
    //------------------------------------------------------------------------------
    // <auto-generated>
    //     此代码由工具生成。
    //     运行时版本:4.0.30319.1026
    //
    //     对此文件的更改可能会导致不正确的行为,并且如果
    //     重新生成代码,这些更改将会丢失。
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    namespace v {
        
        
        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
        [System.ServiceModel.ServiceContractAttribute(ConfigurationName="V.IAjsjService")]
        public interface IAjsjService {
            
            [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IAjsjService/Invoke", ReplyAction="http://tempuri.org/IAjsjService/InvokeResponse")]
            string Invoke(string func, string reqXml);
        }
        
        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
        public interface IAjsjServiceChannel : v.IAjsjService, System.ServiceModel.IClientChannel {
        }
        
        [System.Diagnostics.DebuggerStepThroughAttribute()]
        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
        public partial class AjsjServiceClient : System.ServiceModel.ClientBase<v.IAjsjService>, v.IAjsjService {
            
            public AjsjServiceClient() {
            }
            
            public AjsjServiceClient(string endpointConfigurationName) : 
                    base(endpointConfigurationName) {
            }
            
            public AjsjServiceClient(string endpointConfigurationName, string remoteAddress) : 
                    base(endpointConfigurationName, remoteAddress) {
            }
            
            public AjsjServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
                    base(endpointConfigurationName, remoteAddress) {
            }
            
            public AjsjServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                    base(binding, remoteAddress) {
            }
            
            public string Invoke(string func, string reqXml) {
                return base.Channel.Invoke(func, reqXml);
            }
        }
    }
    复制代码

    调用方法:

    定义soapheader

    复制代码
    public class MySoapHeader
        {
            string username;//用户名
            string password;//密码
            string serialNo;//序列号
    
            public MySoapHeader()
            { }
    
            public MySoapHeader(string u, string p, string s)
            {
                Username = u;
                Password = p;
                SerialNo = s;
            }
    
            public string Username
            {
                get { return username; }
                set { username = value; }
            }
    
            public string Password
            {
                get { return password; }
                set { password = value; }
            }
            public string SerialNo
            {
                get { return serialNo; }
                set { serialNo = value; }
            }
    
        }
    复制代码

    调用

    复制代码
    MySoapHeader myHeader = new MySoapHeader(m_user, m_pw, m_serial);
    
                ServiceReference.AjsjServiceClient client = new ServiceReference.AjsjServiceClient("BasicHttpBinding_IAjsjService", m_serverUrl);
                using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
                {
                   
                   MessageHeader header = MessageHeader.CreateHeader("Authentication", "http://ant.com", myHeader);
                    OperationContext.Current.OutgoingMessageHeaders.Add(header);
                    client.Invoke(func, strXml);
                   
    复制代码

    1.直接调用

    已知webservice路径,则可以直接 添加服务引用--高级--添加web引用 直接输入webservice URL。这个比较常见也很简单

    即有完整的webservice文件目录如下图所示,

    也可以在本地IIS根据webservice文件目录新发布一个webservice,然后程序动态调用,修改Url

    1
    public new string Url { setget; }

    2.根据wsdl文件生成webservice 的.cs文件 及 生成dll C#调用  

    有时没有这么多文件,只有wsdl文件

    wsdl文件可以有别人提供或者根据webservice地址获取:

    http://localhost:8888/WS.asmx?wsdl

    Visual Studio 2013->Visual Studio Tools->VS2013 开发人员命令提示

    命令行输入

    wsdl E:WS.wsdl /out:WS.cs

     
    E:WS.wsdl  是wsdl文件存储路径,也可以是http://localhost:8888/WS.asmx?wsdl
     
    不报错的话,看路径下 Program FilesMicrosoft Visual Studio 12.0WS.cs已经自动生成
     
    .cs文件看函数声明,结构体等都非常方便
     
    然后命令行执行
    csc /t:library WS.cs
     
    同样的路径下,生成了WS.dll,拷贝出去放到项目文件夹下,C# winform程序也可以添加引用了。
     
    生成的文件默认在这里:
     
     
     
    默认生成的SOAP版本为1.1,可以

    G:Program FilesMicrosoft Visual Studio 12.0>wsdl E:e.wsdl /protocol:SOAP12 /out:e.cs

    来指定1.2

     
     

    3.C# 动态调用WebService  

    在C#程序中,若要调用WebService,一般是采用"添加Web引用"的方式来实现的。但如果此WebService的URL是在程序运行过程中才能获得的,那怎么办呢?那就必须是"动态"调用这个WebService了。

     
    举个使用它的例子:
     object[] args = new object[1];  
     args.SetValue("cyy_JS", 0);             
    DataTable dt = WebServiceHelper.InvokeWebService("http://192.168.0.10/DBMS_CYY/DBMS_Service.asmx", "GetUserTreeListData", args) as DataTable;
     
    恩~有点麻烦,这意味着每次我都要把想调用的函数的参数组织成一个object[]才行,且每次调用InvokeWebService都是在内存中创建动态程序集,效率极低。则次种方法绝对没有直接用“实例名.方法名(参数列表)”来的舒服。
     
    我把它放到一个叫WebServiceHelper.cs的类里面了。
     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    using System.IO;
    using System.Web.Services.Description;
    using Microsoft.CSharp;
    using System.CodeDom.Compiler;
    using System.CodeDom;
      
    /// <summary>  
            /// 动态调用WebService  
            /// </summary>  
            /// <param name="url">WebService地址</param>  
            /// <param name="classname">类名</param>  
            /// <param name="methodname">方法名(模块名)</param>  
            /// <param name="args">参数列表</param>  
            /// <returns>object</returns>  
            public static object InvokeWebService(string url, string classname, string methodname, object[] args) 
            
                string @namespace "ServiceBase.WebService.DynamicWebLoad"
                if (classname == null || classname == ""
                
                    classname = WebServiceHelper.GetClassName(url); 
                
                //获取服务描述语言(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 StringBuilder(); 
                    foreach (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, truetrue); 
                object obj = Activator.CreateInstance(t); 
                System.Reflection.MethodInfo mi = t.GetMethod(methodname); 
                return mi.Invoke(obj, args); 
            
       
            private static string GetClassName(string url) 
            
                string[] parts = url.Split('/'); 
                string[] pps = parts[parts.Length - 1].Split('.'); 
                return pps[0]; 
            

      

    参考 http://blog.csdn.net/chuxiamuxiang/article/details/5731988

  • 相关阅读:
    MYSQL学习笔记——sql语句优化工具
    SQL优化工具SQLAdvisor使用
    SqlServer性能检测和优化工具使用详细
    Sql优化器究竟帮你做了哪些工作
    通俗易懂的php多线程解决方案
    PHP删除数组中空值的方法介绍
    PHP函数
    python函数回顾:dir()
    面向对象封装思想小结
    python函数回顾:all()
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/13303613.html
Copyright © 2020-2023  润新知