1

.Netソリューションを介してサードパーティのAXISWebサービスに電話をかけています

次のWSDLファイルを介してVSプロジェクトにサービス参照を追加しました(使用が制限されているため、サービスの場所は削除されました)

<?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」を呼び出した後の実際のレスポンスオブジェクト(StatusInfoのタイプ)が作成されますが、値はゼロ(intプロパティの場合)で、文字列は空です(stringプロパティの場合)。 。)

これは、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>

特定の名前空間と名前空間の参照の不一致が問題になる可能性があることを読みましたが、どちらを見つけることができません。どんな助けでも大歓迎です。

4

2 に答える 2

2

ここで説明されているように、Client Message Inspector を作成することで、応答を操作することができました。

WCF を回避する方法 プレビューの欠如

@SixtoSeazと一緒に提案されたSO Answer:

そう答え

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);
        }
    }

}

そして、Behavior を EndPoint に割り当てます (Service Reference は PMGReference です)。

MyBehavior behavior = new MyBehavior();
PMGReference.PremiumChargingPortTypeClient client = new PMGReference.PremiumChargingPortTypeClient();
client.Endpoint.Behaviors.Add(behavior);
于 2012-04-10T16:35:21.087 に答える
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 を作成しています。サービス構成を変更できる場合は、このフォームの投稿を見て、このタイプのエンコードを回避する方法を確認してください。別のオプションとして、生成されたサービス データ コントラクトを取得し、このSOの回答に従って手動で変更することもできます。

于 2012-04-09T20:23:44.390 に答える