我想用WCF服務替換一個asmx WebService。我的主要目標是保持SOAP消息相同。調用者不是.NET,需要大量的重新工作才能對合同進行微小的更改。可以將單個數組作爲參數的WCF操作使用MessageContracts嗎?
我的痛點是,Web方法,我試圖取代的webmethod使用下列屬性減速:
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
這消除了圍繞每一個參數的XML元素的一個額外層。
我知道使用WCF模擬此的唯一方法是使用MessageContracts而不是DataContracts,並使用WrappedName和IsWrapped屬性來控制參數如何格式化。
這種方法適用於我所有的方法,除了一個,它將一個POCO對象的單個數組作爲參數。
我的結論是,我沒有選擇。我無法升級這個webservice並維護同一個合同。
我的問題是:
1)是複製的唯一途徑:
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
在WCF Web方法使用MessageContract?
2)有沒有辦法讓一個方法把一個數組作爲參數?
下面是一個簡單實施例I一直在努力,以顯示我所看到/用做 [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對象:(V2與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 SOAP請求(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%。
的問題是,我想實現這樣的WCFand的方法守合同相同:
[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的類型時,該方法不得使用任何其他類型的參數。
感謝, 布賴恩
Marc, 我很感謝您的回覆。 我已經添加了關於SoapParameterStyle.Bare的通用代碼示例,以及我如何使用消息合約來替換asmx Soap格式。 我的意圖不是說我必須使用IsWrapped = true,而是使用屬性屬性來獲得預期的效果。我希望我的樣品能澄清我的意思。 在這種情況下,「非常接近」並不夠接近。我可能能夠處理元素名稱的變化,但是如果元素嵌套發生變化,我就會遇到問題。 – 2010-03-05 20:37:04