这两天做与公司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>
将原有报文头对象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;
改造完毕,然后再进行访问,就会生成如下报文:
显示发送成功。