2

この記事を読んだ後:

XML メッセージ設計による Web サービスの相互運用性の向上

既存のメッセージ設計スキーマを新しい SOAP サービスの WSDL にインポートしてみることにしました。

これはすべて VS2008 と .NET 3.5 であり、Altova XMLSpy 2009 はスキーマと wsdl の設計に使用されました。

だから私は次のことをしました:

  1. カスタム WSDL を作成し、XSD インターフェイス仕様をインポートします。
  2. WSDL.EXE を使用してサーバー スタブ コードを生成する
  3. XSD を Web サービス プロジェクトに含める
  4. Linq To Xsdを使用して、使用する厳密に型指定された XDocument ラッパーを生成します
  5. 生成されたスタブ コードを手動で編集して、冗長な自動生成されたラッパー クラスを削除します。
  6. スタブ コードを手動で編集して、WSDL の型を Linq2Xsd で生成されたラッパーにマップします。
  7. WSDL 生成を無効にし、カスタム WSDL を明示的に参照します。WebServiceBindingAttribute
  8. 通常の Web 参照を使用して Win フォーム テスト リグを作成する

OK、問題は次のとおりです。

SOAP リクエストは完全に機能し、パラメーターのシリアライゼーションとデシリアライゼーションは機能します。問題の SOAP 応答、シリアライゼーションが不適切な形式の Xml を作成しており、クライアント デ シリアライゼーションが機能していません。

SOAP 応答は次のとおりです。

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <GetCameraLocationsTableResponse xmlns="http://blah">
            <GetCameraLocationsTableResponse Version="1.0rc2">
                <Response>
                    <Success>true</Success>
                </Response>
                <CameraLocationsTable/>
            </GetCameraLocationsTableResponse>
        </GetCameraLocationsTableResponse>
    </soap:Body>
</soap:Envelope>

ネストされたGetCameraLocationsTableResponse要素に注意してください。これは間違っています。XDocument ラッパーが内部を作成しGetCameraLocationsTableResponse、SOAP メッセージ ジェネレーターの内部動作の何かが外部を追加するGetCameraLocationsTableResponse ことを確認しました。

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <GetCameraLocationsTableResponse Version="1.0rc2" xmlns="http://blah">
            <Response>
                <Success>true</Success>
            </Response>
            <CameraLocationsTable/>
        </GetCameraLocationsTableResponse>
    </soap:Body>
</soap:Envelope>

クライアントのプロキシ コードは正しくシリアル化されますが、サーバーのプロキシ コードは正しくシリアル化されません。もちろん、これは私がいじったサーバー コードです。

Blah名前は罪のない人を保護するために変更されました。

参考までに、編集したサーバー側のプロキシ コードを次に示します。

[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
[System.Web.Services.WebServiceBindingAttribute(Name = "Blah", Namespace = "http://Blah", Location = @"http://localhost:57264/wsdl/Blah.wsdl")]
public interface IBlah
{

    [System.Web.Services.WebMethodAttribute()]
    [SoapLogger]
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]
    [return: System.Xml.Serialization.XmlElementAttribute("GetCameraLocationsTableResponse", Namespace="http://Blah")]
    GetCameraLocationsTableResponse GetCameraLocationsTable([System.Xml.Serialization.XmlElementAttribute(Namespace="http://Blah")] NativeCaseInterfaceDelegateRequest NativeCaseInterfaceDelegateRequest);
}

上記をWebサービスとして実装するために書いたコードは次のとおりです。

[WebService(Namespace = "http://blah")]
public class Blah : WebService, IBlah
{
    #region IBlah Members

    public GetCameraLocationsTableResponse GetCameraLocationsTable(Blah BlahRequest)
    {
        return BlahTools.GetCameraLocationsTable(BlahRequest);
    }

    #endregion
}

ここから system.diagnostics スイッチを使用して、自動生成されたシリアル化コードを抽出することができました。

    protected override void Serialize(object objectToSerialize, System.Xml.Serialization.XmlSerializationWriter writer) {
        ((XmlSerializationWriter1)writer).Write3_Item((object[])objectToSerialize);
    }

    public void Write3_Item(object[] p) {
        WriteStartDocument();
        TopLevelElement();
        int pLength = p.Length;
        if (pLength > 0) {
            WriteSerializable((System.Xml.Serialization.IXmlSerializable)((global::blah.GetCameraLocationsTableResponse)p[0]), @"GetCameraLocationsTableResponse", @"http://blah", false, true);
        }
    }

カスタム WSDL は次のとおりです。

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:sis="http://Blah" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://Blah">
    <wsdl:import namespace="http://Blah" location="Blah.xsd"/>
    <wsdl:message name="BlahRequestMessage">
        <wsdl:part name="in" element="sis:BlahRequest"/>
    </wsdl:message>
    <wsdl:message name="GetCameraLocationsTableResponseMessage">
        <wsdl:part name="out" element="sis:GetCameraLocationsTableResponse"/>
    </wsdl:message>
    <wsdl:portType name="BlahPort">
        <wsdl:operation name="GetCameraLocationsTable">
            <wsdl:input message="sis:BlahRequestMessage"/>
            <wsdl:output message="sis:GetCameraLocationsTableResponseMessage"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="Blah" type="sis:BlahPort">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="GetCameraLocationsTable">
            <soap:operation soapAction="" style="document"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
</wsdl:definitions>

読んでくれてありがとう、

ジェームズ。

4

0 に答える 0