【问题标题】:Can a WCF Operation that takes a single array as a parameter use MessageContracts?将单个数组作为参数的 WCF 操作可以使用 MessageContracts 吗?
【发布时间】:2011-01-24 06:37:11
【问题描述】:

我正在尝试用 WCF 服务替换 asmx WebService。我的主要目标是保持 SOAP 消息相同。调用者不是 .NET,需要大量返工才能对合同进行细微更改。

我的痛点是我试图替换 webmethod 的 web 方法使用以下属性减速:

[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]

这会移除每个参数周围的额外 XML 元素层。

我知道使用 WCF 进行模拟的唯一方法是使用 MessageContracts 而不是 DataContracts,并使用 WrappedName 和 IsWrapped 属性来控制参数的格式。

这种方法适用于我的所有方法,除了一个方法,它采用 POCO 对象的单个数组作为参数。

我的结论是我别无选择。我无法升级此 Web 服务并维护相同的合同。

我的问题是:

1) 是唯一的复制方式:

    [SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]

在 WCF 中的 Web 方法上使用 MessageContract?

2) 有没有办法让方法将单个数组作为参数?

这是我一直在使用的一个简单示例,用于展示我所看到的/正在做的事情 [SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)] 和消息契约

后台服务代码:

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 SOAP

<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 对象:(带有 MessageContracts 的 V2)

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 类型,我无法更改。

无法加载操作“AddArrays”,因为它具有 System.ServiceModel.Channels.Message 类型的参数或返回类型,或者具有 MessageContractAttribute 和其他不同类型参数的类型。当使用 System.ServiceModel.Channels.Message 或带有 MessageContractAttribute 的类型时,该方法不得使用任何其他类型的参数。

谢谢, 布赖恩

【问题讨论】:

    标签: .net wcf soap messagecontract


    【解决方案1】:

    我有点被你的说法难住了,SoapParameterStyle.Bare 删除了参数周围的一层 XML,但你只能通过使用带有 IsWrapped=true 的消息契约来复制它,而这又基本上是 添加 又是一个围绕 SOAP 有效负载的 XML 包装器……似乎有点矛盾。

    您能否向我们展示您的方法的 Web 方法声明,该方法将 POCO 数组作为其参数?到目前为止,您在 WCF 中尝试过什么?通常情况下,使用 BasicHttpBinding 并且几乎没有任何选项,您会非常接近 ASMX 在过去所做的事情。

    【讨论】:

    • 马克,感谢您的回复。我添加了围绕 SoapParameterStyle.Bare 的通用代码示例,以及我如何使用消息契约来替换 asmx Soap 格式。我的意图并不是说我必须使用 IsWrapped=true,而是使用属性属性来获得预期的效果。我希望我的样本能阐明我的意思。在这种情况下,“非常接近”还不够接近。我可能能够处理元素名称的变化,但如果元素的嵌套发生变化,我就会遇到问题。
    【解决方案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 从请求中删除了该类的所有表示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-03
      • 1970-01-01
      • 1970-01-01
      • 2014-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多