Я пытаюсь заменить asmx WebService на службу WCF.Моя основная цель - сохранить сообщение SOAP таким же.Вызывающая сторона не является .NET, и для внесения незначительных изменений в контракт потребуется значительная доработка.
Моя главная проблема в том, что веб-методы, которые я пытаюсь заменить webmethod, используют следующее замедление атрибута:
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
При этом удаляется дополнительный слой элементов XML вокруг каждого параметра.
Единственный известный мне способ моделирования этого с WCF - это использование MessageContracts вместо DataContracts и использование WrappedNameи свойство IsWrapped для управления форматированием параметров.
Этот подход работает для всех моих методов, кроме одного, в котором в качестве параметра используется один массив объекта POCO.
Мой выводчто у меня нет вариантов.Я не могу обновить этот веб-сервис и поддерживать тот же контракт.
Мои вопросы:
1) Есть ли единственный способ реплицироваться:
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
на веб-метод в WCF для использования 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: (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 Request (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 метод не должен использовать какие-либо другие типы параметров.
Спасибо, Брайан