我通过.Net解决方案呼叫第三方的AXIS网络服务
通过以下WSDL文件为我的VS Project添加了服务引用(服务位置已被删除,因为它是受限制的用法)
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
name="PremiumCharging"
targetNamespace="http://premiumcharging.verisign.com"
xmlns:pmg="http://types.premiumcharging.verisign.com"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://premiumcharging.verisign.com"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<xsd:schema
targetNamespace="http://types.premiumcharging.verisign.com"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:pmg="http://types.premiumcharging.verisign.com"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="UserInfo">
<xsd:sequence>
<xsd:element name="aggregatorId" type="xsd:int"/>
<xsd:element name="pwd" type="xsd:string"/>
<xsd:element name="version" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="StatusInfo">
<xsd:sequence>
<xsd:element name="errorCode" type="xsd:int"/>
<xsd:element name="errorDescription" type="xsd:string"/>
<xsd:element name="transactionId" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="chargeSubscriberResponse">
<wsdl:part name="chargeSubscriberReturn" type="pmg:StatusInfo"/>
</wsdl:message>
<wsdl:message name="chargeSubscriberRequest">
<wsdl:part name="user" type="pmg:UserInfo"/>
<wsdl:part name="mdn" type="xsd:string"/>
<wsdl:part name="productId" type="xsd:string"/>
<wsdl:part name="shortCode" type="xsd:string"/>
<wsdl:part name="carrierId" type="xsd:int"/>
<wsdl:part name="chargeId" type="xsd:string"/>
<wsdl:part name="msgtxid" type="xsd:string"/>
</wsdl:message>
<wsdl:portType name="PremiumChargingPortType">
<wsdl:operation name="chargeSubscriber">
<wsdl:input message="tns:chargeSubscriberRequest"/>
<wsdl:output message="tns:chargeSubscriberResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="PremiumChargingBinding" type="tns:PremiumChargingPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="chargeSubscriber">
<soap:operation/>
<wsdl:input>
<soap:body parts="user mdn productId shortCode carrierId chargeId msgtxid" use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body parts="chargeSubscriberReturn" use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="PremiumCharging">
<wsdl:port binding="tns:PremiumChargingBinding" name="PremiumChargingPort">
<soap:address location="...location removed..."/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
我能够生成一个请求并收到一个响应(通过Fiddler捕获),但是在调用“chargeSubscriber”之后创建了实际响应对象(typeof StatusInfo)但是没有值(对于int属性)和空字符串(对于字符串属性。)
这是Fiddler中捕获的响应XML的一个示例:
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<chargeSubscriberResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<chargeSubscriberReturn href="#id0"/>
</chargeSubscriberResponse>
<multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns1:StatusInfo" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://types.premiumcharging.verisign.com">
<errorCode href="#id1"/>
<errorDescription xsi:type="soapenc:string">Non-Carrier MIN</errorDescription>
<transactionId href="#id2"/>
</multiRef>
<multiRef id="id2" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">2216</multiRef>
<multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">-105</multiRef>
</soapenv:Body>
</soapenv:Envelope>
我已经读过某些命名空间和命名参考不匹配可能是一个问题,但我无法找到哪个。任何帮助表示赞赏。
答案 0 :(得分:2)
我能够通过创建客户端消息检查器来操作响应,如下所述:
How to Get Around WCFs Lack of a preview
与@SixtoSeaz一起建议SO答案:
在Client Message Inspector的方法“AfterReceiveReply”中,我通过在引用multiRef项的每个节点上分配InnerXml来更改SOAP响应。然后,StatusInfo响应对象确实获得了根据需要填充的正确值。
行为和ClientMessageInspector:
public class MyBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new MyMessageInspector());
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
public class MyMessageInspector : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(reply.ToString());
List<XmlElement> items = new List<XmlElement>();
Dictionary<string, XmlElement> multiRefs = new Dictionary<string,XmlElement>();
InspectNodes(doc.DocumentElement, items, multiRefs);
FixNodes(items, multiRefs);
MemoryStream ms = new MemoryStream();
XmlWriter writer = XmlWriter.Create(ms);
doc.WriteTo(writer);
writer.Flush();
ms.Position = 0;
XmlReader reader = XmlReader.Create(ms);
reply = Message.CreateMessage(reader, int.MaxValue, reply.Version);
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
return null;
}
private static void InspectNodes(XmlElement element, List<XmlElement> items, Dictionary<string, XmlElement> multiRefs)
{
string val = element.GetAttribute("href");
if (val != null && val.StartsWith("#id"))
items.Add(element);
else if (element.Name == "multiRef")
multiRefs[element.GetAttribute("id")] = element;
foreach (XmlNode node in element.ChildNodes)
{
XmlElement child = node as XmlElement;
if (child != null)
InspectNodes(child, items, multiRefs);
}
}
private static void FixNodes(List<XmlElement> items, Dictionary<string, XmlElement> multiRefs)
{
// Reverse order so populate the id refs into one single element. This is only a solution in relation to the WSDL definition.
for (int x = items.Count - 1; x >= 0; x--)
{
XmlElement element = items[x];
string href = element.GetAttribute("href");
if (String.IsNullOrEmpty(href))
continue;
if (href.StartsWith("#"))
href = href.Remove(0, 1);
XmlElement multiRef = multiRefs[href];
if (multiRef == null)
continue;
element.RemoveAttribute("href");
element.InnerXml = multiRef.InnerXml;
multiRef.ParentNode.RemoveChild(multiRef as XmlNode);
}
}
}
然后将行为分配给EndPoint(服务参考是PMGReference)
MyBehavior behavior = new MyBehavior();
PMGReference.PremiumChargingPortTypeClient client = new PMGReference.PremiumChargingPortTypeClient();
client.Endpoint.Behaviors.Add(behavior);
答案 1 :(得分:1)
此XML架构定义:
<xsd:complexType name="StatusInfo">
<xsd:sequence>
<xsd:element name="errorCode" type="xsd:int"/>
<xsd:element name="errorDescription" type="xsd:string"/>
<xsd:element name="transactionId" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
应该生成看起来像这样的XML(以及WCF期望的那样):
<StatusInfo>
<errorCode>-105</errorCode>
<errorDescription>Non-Carrier MIN</errorDescription>
<transactionId>2216</transactionId>
</StatusInfo>
java服务正在创建使用WCF序列化程序无法理解的常规href / multiref对的XML。如果能够更改服务配置,请查看此form post以了解如何避免此类编码。另一个选择是获取生成的服务数据合同,并按照SO answer.
的方式手动修改它们