在异架构间通讯时,我们一般会采用WS。我遇到的情况是WSDL已经由AXIS生成,我需要用Dotnet实现服务器。
简单实现后,发现里面的 NotifySOAPHeader 总是取不值,添加 SoapUnknownHeader[] 后,里面有值。可见是不能识别AXIS发送来的SoapHeader。
仔细对比Dotnet生成的WSDL,和原来的定义的WSDL相关内容:
DotNet' WSDL
<s:complexType name="NotifySOAPHeader">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="spRevId" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="spRevpassword" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="spId" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="SAN" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="transactionId" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="linkId" type="s:string" />
</s:sequence>
<s:anyAttribute />
</s:complexType>
<s:complexType name="NotifySOAPHeader">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="spRevId" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="spRevpassword" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="spId" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="SAN" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="transactionId" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="linkId" type="s:string" />
</s:sequence>
<s:anyAttribute />
</s:complexType>
Java's WSDL
<xsd:complexType name="NotifySOAPHeader">
<xsd:sequence>
<xsd:element name="spRevId" type="xsd:string" minOccurs="0" maxOccurs="1"/>
<xsd:element name="spRevpassword" type="xsd:string" minOccurs="0" maxOccurs="1"/>
<xsd:element name="spId" type="xsd:string"/>
<xsd:element name="SAN" type="xsd:string" minOccurs="0" maxOccurs="1"/>
<xsd:element name="transactionId" type="xsd:string" minOccurs="0" maxOccurs="1"/>
<xsd:element name="linkId" type="xsd:string" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="NotifySOAPHeader">
<xsd:sequence>
<xsd:element name="spRevId" type="xsd:string" minOccurs="0" maxOccurs="1"/>
<xsd:element name="spRevpassword" type="xsd:string" minOccurs="0" maxOccurs="1"/>
<xsd:element name="spId" type="xsd:string"/>
<xsd:element name="SAN" type="xsd:string" minOccurs="0" maxOccurs="1"/>
<xsd:element name="transactionId" type="xsd:string" minOccurs="0" maxOccurs="1"/>
<xsd:element name="linkId" type="xsd:string" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
我感觉只有一个区别,就是Dotnet生成的有:form="unqualified" ,而Java原来的没有。所以Dotnet不能识别有Prefix的NodeName,造成不能识别。例如:
Java发过来的 Soap
......
<soapenv:Header>
<NotifySOAPHeader xmlns="http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1">
<spId>07119935</spId>
<spRevId>07119935</spRevId>
<spRevpassword>vY95rHCNmj8JAeanlPhL8g==</spRevpassword>
</NotifySOAPHeader>
</soapenv:Header>
......
......
<soapenv:Header>
<NotifySOAPHeader xmlns="http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1">
<spId>07119935</spId>
<spRevId>07119935</spRevId>
<spRevpassword>vY95rHCNmj8JAeanlPhL8g==</spRevpassword>
</NotifySOAPHeader>
</soapenv:Header>
......
Dotnet 要求的格式
<soapenv:Header>
<NotifySOAPHeader xmlns="http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1">
<spId xmlns="">07119935</spId>
<spRevId xmlns="">07119935</spRevId>
<spRevpassword xmlns="">>vY95rHCNmj8JAeanlPhL8g==</spRevpassword>
</NotifySOAPHeader>
</soapenv:Header>
<soapenv:Header>
<NotifySOAPHeader xmlns="http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1">
<spId xmlns="">07119935</spId>
<spRevId xmlns="">07119935</spRevId>
<spRevpassword xmlns="">>vY95rHCNmj8JAeanlPhL8g==</spRevpassword>
</NotifySOAPHeader>
</soapenv:Header>
就因为有一个 xmlns="",造成不能识别该SoapHeader。当然修正的方法也很简单,只要把NotifySOAPHeader的每个属性的元数据修改一下,像下面的示例:
原来生成的代码
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1")]
[System.Xml.Serialization.XmlRootAttribute("NotifySOAPHeader",Namespace = "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1", IsNullable = false)]
public class NotifySOAPHeader : System.Web.Services.Protocols.SoapHeader
{
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string spRevId;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string spRevpassword;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string spId;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string SAN;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string transactionId;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string linkId;
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1")]
[System.Xml.Serialization.XmlRootAttribute("NotifySOAPHeader",Namespace = "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1", IsNullable = false)]
public class NotifySOAPHeader : System.Web.Services.Protocols.SoapHeader
{
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string spRevId;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string spRevpassword;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string spId;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string SAN;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string transactionId;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string linkId;
}
修正为:
修正后的类实现
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1")]
[System.Xml.Serialization.XmlRootAttribute("NotifySOAPHeader",Namespace = "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1", IsNullable = false)]
public class NotifySOAPHeader : System.Web.Services.Protocols.SoapHeader
{
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
public string spRevId;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
public string spRevpassword;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
public string spId;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
public string SAN;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
public string transactionId;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
public string linkId;
}
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1")]
[System.Xml.Serialization.XmlRootAttribute("NotifySOAPHeader",Namespace = "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1", IsNullable = false)]
public class NotifySOAPHeader : System.Web.Services.Protocols.SoapHeader
{
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
public string spRevId;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
public string spRevpassword;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
public string spId;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
public string SAN;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
public string transactionId;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
public string linkId;
}
这样就可以了,不用再写代码从SoapUnknownHeader中取数据了。也没有必须为Java和Dotnet分别写一份代码。
是不是以后用Dotnet发布时,都用上这个声明呢?我经验不多,大家讨论一下。