我正在尝试用 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 肥皂
<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 的类型时,该方法不得使用任何其他类型的参数。
谢谢,布赖恩