4

asmx WebService を WCF サービスに置き換えようとしています。私の主な目標は、SOAP メッセージを同じに保つことです。呼び出し元は .NET ではないため、コントラクトに小さな変更を加えるには大幅な再作業が必要になります。

私の問題点は、webmethod を置き換えようとしている Web メソッドが次の属性減速を使用することです。

[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]

これにより、各パラメーターの周りの XML 要素の余分なレイヤーが削除されます。

これを WCF でシミュレートする方法として私が知っている唯一の方法は、DataContracts の代わりに MessageContracts を使用し、WrappedName と IsWrapped プロパティを使用してパラメーターのフォーマット方法を制御することです。

このアプローチは、POCO オブジェクトの 1 つの配列をパラメーターとして受け取る 1 つを除いて、すべてのメソッドで機能します。

私の結論は、私には選択肢がないということです。この Web サービスをアップグレードして、同じ契約を維持することはできません。

私の質問は次のとおりです。

1)複製する唯一の方法です:

    [SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]

MessageContractを使用するWCFのWebメソッドで?

2)そして、メソッドが単一の配列をパラメータとして取る方法はありますか?

これは、私が見ているものを示すために取り組んできた簡単な例です/ [SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)] と Message Contract を使用して実行しています

バッキング サービス コード:

using System.Web.Services;
using System.Web.Services.Protocols;
using System.ServiceModel;
namespace WebApplication1{

    /// <summary>
    /// The Service Contract
    /// </summary>
    [ServiceContract]
    public interface ISimpleMathService
    {
        [OperationContract()]
        AddResp Add(AddReq add);
    }
    /// <summary>
    /// The Service Implementation
    /// </summary>
    public class simpleMath : ISimpleMathService
    {
        [WebMethod()] //Allows the Service to be exposed as a asmx Service
        [SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
        public AddResp Add(AddReq add)
        {
            return new AddResp {result = add.NumOne + add.NumTwo}; 
        }
    }
}

POCO オブジェクト: (V1 とデータ コントラクト)

    using System.Runtime.Serialization;
using System.ServiceModel;

namespace WebApplication1
{
    [DataContract]
    public class AddReq
    {

        [DataMember]
        public int NumOne { get; set; }

        [DataMember]
        public int NumTwo { get; set; }
    }



    [DataContract]
    public class AddResp
    {

        [DataMember]

        public int result{ get; set; }


    }
}

ASMX ソープ

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
   <soapenv:Header/>
   <soapenv:Body>
      <tem:add>
         <tem:NumOne>12</tem:NumOne>
         <tem:NumTwo>12</tem:NumTwo>
      </tem:add>
   </soapenv:Body>
</soapenv:Envelope>

SOAP 要求、WCF データ コントラクトを使用

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/" xmlns:web="http://schemas.datacontract.org/2004/07/WebApplication1">
   <soap:Header/>
   <soap:Body>
      <tem:Add>
         <tem:add>
            <web:NumOne>10</web:NumOne>
            <web:NumTwo>10</web:NumTwo>
         </tem:add>
      </tem:Add>
   </soap:Body>
</soap:Envelope>

引数と戻り値の型でメッセージ コントラクトを使用しましょう: POCO オブジェクト: (V2 with MessageContracts)

namespace WebApplication1
{
    [DataContract]
    [MessageContract(WrapperName="add", IsWrapped = true)] //Default Wrapper Name is "Add", not add
    public class AddReq
    {

        [DataMember]
        [MessageBodyMember]
        public int NumOne { get; set; }

        [DataMember]
        [MessageBodyMember]
        public int NumTwo { get; set; }
    }



    [DataContract]
    [MessageContract(IsWrapped = true)]
    public class AddResp
    {

        [DataMember]
        [MessageBodyMember]
        public int result{ get; set; }


    }
}

WCF ソープ リクエスト (V2):

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/">
   <soap:Header/>
   <soap:Body>
      <tem:add>
         <tem:NumOne>19</tem:NumOne>
         <tem:NumTwo>12</tem:NumTwo>
      </tem:add>
   </soap:Body>
</soap:Envelope>

それが今私がしていることで、必要なものの 90% を満たしています。

問題は、WCF でこのようなメソッドを実装し、コントラクトを同じに保ちたいということです。

[WebMethod()]
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
public AddResp AddArrays(AddReq [] addInput)
{
    AddResp resp= new AddResp{result=0}
    foreach (var addrequest in addInput)
    {
        resp.result += (addrequest.NumOne + addrequest.NumTwo);
    }
    return resp;
}

今これを行うと、AddReq [] は MessageContract ではないため、次の例外が発生します。AddReq [] は System.Array 型で、変更できません。

System.ServiceModel.Channels.Message 型のパラメーターまたは戻り値の型、または MessageContractAttribute と異なる型の他のパラメーターを持つ型があるため、操作 'AddArrays' を読み込むことができませんでした。System.ServiceModel.Channels.Message または MessageContractAttribute を持つ型を使用する場合、メソッドは他の型のパラメーターを使用してはなりません。

ありがとう、ブライアン

4

2 に答える 2

2

IsWrapped=false を指定して「ホスト クラス」を追加すると、機能することがわかりました。

元の質問のサンプルから、ラッパー クラスは次のようになります。

[DataContract,MessageContract(IsWrapped=false)]
public class AddArraysReq
{
    [DataMember]
    [MessageBodyMember]
    public AddReq[] AddReqs;

}

メソッドは次のようになります。

 public AddResp AddArrays(AddArraysReq addInput)
    {
        AddResp resp = new AddResp {result = 0};
        foreach (var addrequest in addInput.AddReqs)
        {
            resp.result += (addrequest.NumOne + addrequest.NumTwo);
        }
        return resp;
    }

結果の SOAP リクエスト:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" 
    xmlns:tem="http://tempuri.org/" 
    xmlns:web="http://schemas.datacontract.org/2004/07/WebApplication1">
   <soap:Header/>
   <soap:Body>
      <tem:AddReqs>        
         <web:AddReq>
            <web:NumOne>10</web:NumOne>
            <web:NumTwo>10</web:NumTwo>
         </web:AddReq>
         <web:AddReq>
            <web:NumOne>10</web:NumOne>
           <web:NumTwo>10</web:NumTwo>
         </web:AddReq>
        </tem:AddReqs>
   </soap:Body>
</soap:Envelope>

IsWrapped=false がクラスのすべての表現をリクエストから削除していることに気付きませんでした。

于 2010-03-05T22:13:06.857 に答える
1

パラメータの周りのXMLのレイヤーを削除するあなたのステートメントに少し困惑してSoapParameterStyle.Bareいますが、メッセージコントラクトを使用することによってのみそれを複製できますIsWrapped=true。これにより、基本的にSOAPペイロードの周りにXMLラッパーが再び追加されます...ちょっと矛盾。

POCO の配列をパラメーターとして受け取るメソッドの Web メソッド宣言を見せてもらえますか? これまでに WCF で何を試しましたか? 通常、BasicHttpBindingオプションをほとんど使用せずに、昔の ASMX が行っていたことに非常に近づけることができます。

于 2010-03-05T19:56:00.737 に答える