zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    172. Factorial Trailing Zeroes
    96. Unique Binary Search Trees
    95. Unique Binary Search Trees II
    91. Decode Ways
    LeetCode 328 奇偶链表
    LeetCode 72 编辑距离
    LeetCode 226 翻转二叉树
    LeetCode 79单词搜索
    LeetCode 198 打家劫舍
    LeetCode 504 七进制数
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/13303613.html
Copyright © 2011-2022 走看看