2012-04-09 95 views
1

我通過.NET解決方案SOAP Response對象未填充

新增通過以下WSDL文件中的服務引用到我的VS項目調用第三方的Axis Web服務(服務位置已被刪除,因爲它是一個受限制的使用)

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

我能夠生成請求並接收響應(通過提琴手捕獲),但調用「chargeSubscriber」被創建之後,但具有零個值的實際響應對象(typeof運算StatusInfo)(對於int屬性)和空字符串(用於字符串屬性)。

這是小提琴手捕獲的響應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> 

我已閱讀,某些命名空間和命名參考不匹配可能是一個問題,但我無法找到它。任何幫助表示讚賞。

回答

2

我能夠操縱通過創建客戶端消息檢查的響應如下所述:

How to Get Around WCFs Lack of a preview

與@SixtoSeaz一起提示SO答:

SO Answer

而且在法CLI中的 「AfterReceiveReply」 ent Message Inspector我通過在引用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); 
     } 
    } 

} 

,然後分配行爲的端點(服務引用PMGReference)

MyBehavior behavior = new MyBehavior(); 
PMGReference.PremiumChargingPortTypeClient client = new PMGReference.PremiumChargingPortTypeClient(); 
client.Endpoint.Behaviors.Add(behavior); 
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服務是創建使用慣例對XML href/multiref,WCF序列化程序不能理解。看看這個form post看看如何避免這種類型的編碼,如果你能夠改變服務配置。另一個選項可以是取生成的服務數據契約並手動修改它們沿行此SO answer.

+0

我沒有訪問AXIS服務(第三方),以避免作爲你的論壇參考建議發送multiRef的響應。所以,這可不是我需要的解決方案。 – Quintium 2012-04-09 20:32:07

+0

在這種情況下,您將不得不手動修改您生成的數據合同類,以便根據添加到我的答案中的鏈接的行來「理解」multiRef約定。我不認爲從[WCF Express Interop](http://wcf.codeplex.com/wikipage?title=WCF%20Express%20Interop%20Bindings)綁定集合中專門爲Axis使用綁定將有所幫助,但它可能是值得的一試。 – 2012-04-09 20:37:44

+0

另請參閱http://www.tomergabel.com/GettingWCFAndApacheAxisToBeFriendly.aspx。您可以問供應商他們是否有提供文檔/文字的端點而不是RPC編碼的SOAP? – JamieSee 2012-04-09 21:00:06