這兩天做與公司OA的接口,發現C#訪問Java的WebService需要提供一個SOAP的頭驗證信息,但是WebService的WSDL中並沒有提供約定的驗證信息,所以Visual Studio生成的代理類並沒有發現這些內容,所以這個SOAPHeader就必須要自己組織,還遇到一個問題就是SOAP頭部信息,OA那邊還按照不知道什么實例添加了一個根節點沒有的命名空間,這就致使SOAPHeader內容一直報傳輸錯誤,廢話不多說,上兩個階段的示例。
首先,要創建一個繼承自System.Web.Services.Protocols.SoapHeader的RequestSOAPHeader類,在其中添加UserName和Password兩個屬性,代碼如下:
public
class
RequestSOAPHeader
: System.Web.Services.Protocols.
SoapHeader
{
public
string
user {
get
;
set
; }
public
string
password {
get
;
set
; }
}
生成的WebService代理類中設置成屬性成員:
public
partial
class
ISysNotifyTodoWebServiceService
{
public
RequestSOAPHeader
RequestSOAPHeader {
get
;
set
; }
}
在訪問的WebService方法上方添加SOAPHeader的聲明:
[System.Web.Services.Protocols.
SoapDocumentMethodAttribute
(
""
, RequestNamespace=
"http://webservice.notify.sys/"
, ResponseNamespace=
"http://webservice.notify.sys/"
, Use=System.Web.Services.Description.
SoapBindingUse
.Literal, ParameterStyle=System.Web.Services.Protocols.
SoapParameterStyle
.Wrapped)]
[
return
: System.Xml.Serialization.
XmlElementAttribute
(
"return"
, Form=System.Xml.Schema.
XmlSchemaForm
.Unqualified)]
[ SoapHeader( "RequestSOAPHeader")]
public
notifyTodoAppResult
setTodoDone([System.Xml.Serialization.
XmlElementAttribute
(Form=System.Xml.Schema.
XmlSchemaForm
.Unqualified)]
notifyTodoRemoveContext
arg0) {
object
[] results =
this
.Invoke(
"setTodoDone"
,
new
object
[] {
arg0});
return
((
notifyTodoAppResult
)(results[0]));
}
發送報文截圖如下:

結果返回用戶名密碼錯誤:

查OA系統訪問文檔,才發現SOAPHeader需要放在特殊的命名空間內容,但是因為原WSDL可能因為安全原因就沒有任何顯式聲明,經過一番折騰終於明白如何去改造WebService代理類在報文節點上面加自定義的命名空間和前綴。原報文要求如下:
<RequestSOAPHeader xmlns:tns="http://sys.webservice.client">
<tns:UserName>
username
</tns:UserName>
<tns:Password>
password
</tns:Password>
</RequestSOAPHeader>
<tns:UserName>
username
</tns:UserName>
<tns:Password>
password
</tns:Password>
</RequestSOAPHeader>
將原有報文頭對象RequestSOAPHeader更改為:
public
class
RequestSOAPHeader
: System.Web.Services.Protocols.
SoapHeader
{
public
RequestSOAPHeader()
{
Namespaces =
new
XmlSerializerNamespaces
();
}
[
XmlElement
(Namespace =
"http://sys.webservice.client"
)]
public
string
UserName{
get
;
set
; }
[
XmlElement
(Namespace =
"http://sys.webservice.client"
)]
public
string
Password {
get
;
set
; }
[
XmlNamespaceDeclarations
]
public
XmlSerializerNamespaces
Namespaces {
get
;
set
; }
}
然后在代理類的構造函數中實例化RequestSOAPHeader對象時,將需要的命名空間定義添加到Namespaces中:
RequestSOAPHeader =
new
OA.
RequestSOAPHeader
();
RequestSOAPHeader.Namespaces.Add(
"tns"
,
"http://sys.webservice.client"
);
RequestSOAPHeader.UserName=Settings.Default.ConnectUserName;
RequestSOAPHeader.Password=Settings.Default.ConnectPassword;
改造完畢,然后再進行訪問,就會生成如下報文:

顯示發送成功。