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,兩個參數,自行理解吧

注意:里面的\r\n換行標志都要保留,不然都是報錯

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\"?>\r\n"  +
                "<SOAP-ENV:Envelope\r\n"  +
                "xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\r\n"  +
                "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\r\n"  +
                "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n"  +
                "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n"  +
                "<SOAP-ENV:Header>\r\n"  +
                    "<vc:Authentication\r\n"  +
                        "xmlns:vc=\"http://ant.com\">\r\n"  +
                        "<vc:Username>xx</vc:Username>\r\n"  +
                        "<vc:Password>xxx</vc:Password>\r\n"  +
                        "<vc:SerialNo>xxxx</vc:SerialNo>\r\n"  +
                    "</vc:Authentication>\r\n"  +
                "</SOAP-ENV:Header>\r\n"  +
                "<SOAP-ENV:Body>\r\n"  +
                    "<m:Invoke\r\n"  +
                        "xmlns:m=\"http://tempuri.org/\">\r\n"  +
                        "<m:func>"  + jkid +  "</m:func>\r\n"  +
                        "<m:reqXml>"  + HttpUtility.HtmlEncode(xml) +  "</m:reqXml>\r\n"  +
                    "</m:Invoke>\r\n"  +
                "</SOAP-ENV:Body>\r\n"  +
                "</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 {  set get ; }

 

 

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 Files\Microsoft Visual Studio 12.0\WS.cs已經自動生成
 
.cs文件看函數聲明,結構體等都非常方便
 
然后命令行執行
csc /t:library WS.cs
 
同樣的路徑下,生成了WS.dll,拷貝出去放到項目文件夾下,C# winform程序也可以添加引用了。
 
生成的文件默認在這里:
 
 
 
默認生成的SOAP版本為1.1,可以

G:\Program Files\Microsoft 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,  true true ); 
             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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM