ServiceStack试图绑定通过服务引用而不是公共属性生成的私有字段类

时间:2018-11-16 10:44:05

标签: c# xml soap servicestack

有一个远程服务,我正在尝试使用SOAP通过http POST请求向我发送消息。我使用集成在Visual Studio中的选项“添加服务参考”生成了服务DTO。

这是一个自动生成的类的示例:

[Route("/test", "POST")]
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "3.0.4506.2152")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, 
Namespace="http://www.reservationassistant.com/Booking/Types")]
public partial class UpdateBookingRequest
{

private Booking bookingField;

private string resortIdField;

/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
public Booking Booking
{
    get
    {
        return this.bookingField;
    }
    set
    {
        this.bookingField = value;
    }
}

当我创建ServiceInterface方法并运行服务时,进入元数据页面,我会收到以下示例SOAP消息

<UpdateBookingRequest>
  <bookingField>
         ....
  <bookingField>
<UpdateBookingRequest>

这是我的服务接口类中的代码:

UpdateBookingResponse Post(UpdateBookingRequest request)
{
    // do stuff with request
    return null;
}

您可能暗指自动生成的类,我收到的消息将具有与生成的DTO中的公共属性相同的标记名。但是,这将永远不可能,因为对于某些原因,ServiceStack试图将传入的XML消息元素绑定到DTO的私有字段(由我的服务的元数据页面生成的示例SOAP消息-请在“预订”后注意“ field”后缀”)。如何使传入消息绑定到公共属性而不是私有字段?

1 个答案:

答案 0 :(得分:1)

首先,如果需要Type C#服务,我强烈建议在C# Add ServiceStack Reference中使用更具弹性,多功能,更清洁和更快的替代方法。 SOAP是slow, fragile and bloated serialization format,只应在旧式集成中考虑。

默认情况下,ServiceStack使用.NET XML DataContract Serializer进行XML或SOAP序列化,因此其行为取决于.NET的XML DataContractSerializer实现。

对于处理SOAP,它使用WCF的通用Message类,默认情况下使用DataContractSerializer,但是您可以通过在您的目录上添加[XmlSerializerFormat] attribute来使用XmlSerializer实现切换为填充WCF的Message请求和响应DTO。

您可以请求.NET的WCF svcutil使用/serializer命令行开关来强制生成DataContract或XmlSerializer类,例如:

svcutil endpoint.wsdl /serializer:DataContractSerializer
svcutil endpoint.wsdl /serializer:XmlSerializer

覆盖ContentTypes

您可以注册custom Content Type来覆盖用于XML请求的Xml序列化,例如您可以覆盖它以使用XmlSerializer实现来处理XML请求,例如:

ContentTypes.Register(MimeTypes.Xml,
    (req, dto, stream) => {
        using (var xw = XmlWriter.Create(stream))
        {
            var ser = new XmlSerializerWrapper(dto.GetType());
            ser.WriteObject(xw, dto);
        }
    },
    (type, stream) => {
        using (var reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas()))
        {
            var serializer = new System.Xml.Serialization.XmlSerializer(type);
            return serializer.Deserialize(reader);
        }                    
    });

用于SOAP请求的元数据预览

当您从元数据预览中推断行为时,请注意,预览不是使用WCF序列化器用于SOAP请求生成的,因此请求正文是使用DataContraceSerializer生成的,因此,如果在WCF消息中使用XmlSerializer实现。