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

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;
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