ServiceStack 尝试绑定通过服务引用而不是 public 属性生成的私有字段 类
ServiceStack trying to bind private fields classes generated via service reference instead of public properties
有一个远程服务,我正在尝试使用 SOAP 通过 http POST 请求向我发送消息。我使用 visual studio 中集成的选项 "Add service reference".
生成了服务 DTO
这是一个自动生成的示例 class:
[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>
这是我的服务接口中的代码class:
UpdateBookingResponse Post(UpdateBookingRequest request)
{
// do stuff with request
return null;
}
正如您可能通过自动生成的 class 暗示的那样,我收到的消息的标签名称将等于生成的 DTO 中的 public 属性。然而,这永远不可能,因为出于某种原因,ServiceStack 试图将传入的 XML 消息元素绑定到 DTO 的私有字段(由我的服务的元数据页面生成的示例 SOAP 消息 - 注意 "field" "booking" 之后的后缀)。如何使传入消息绑定到 public 属性而不是私有字段?
首先,如果您需要类型化的 C# 服务,我强烈建议您在 C# Add ServiceStack Reference. SOAP is a slow, fragile and bloated serialization format 中使用更具弹性、通用性、更清洁和更快的替代方案,这应该只考虑用于遗留集成。
默认情况下,ServiceStack 使用 .NET XML DataContract Serializer 进行 XML 或 SOAP 序列化,因此行为取决于 .NET 的 XML DataContractSerializer
实现。
为了处理 SOAP,它使用 WCF 的通用 Message
class,默认情况下使用 DataContractSerializer
,但您可以切换为使用 XmlSerializer 填充 WCF 的 Message
通过在您的请求和响应 DTO 中添加 [XmlSerializerFormat] attribute 来实现。
您可以请求 .NET 的 WCF svcutil 使用 /serializer
命令行开关强制生成 DataContract 或 XmlSerializer classes,例如:
svcutil endpoint.wsdl /serializer:DataContractSerializer
svcutil endpoint.wsdl /serializer:XmlSerializer
覆盖内容类型
您可以注册一个 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 Serializer for SOAP Requests 生成的,请求正文是使用 DataContraceSerializer
生成的,因此它不会反映相同的内容如果在 WCF 消息中使用 XmlSerializer 实现,则输出。
有一个远程服务,我正在尝试使用 SOAP 通过 http POST 请求向我发送消息。我使用 visual studio 中集成的选项 "Add service reference".
生成了服务 DTO这是一个自动生成的示例 class:
[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>
这是我的服务接口中的代码class:
UpdateBookingResponse Post(UpdateBookingRequest request)
{
// do stuff with request
return null;
}
正如您可能通过自动生成的 class 暗示的那样,我收到的消息的标签名称将等于生成的 DTO 中的 public 属性。然而,这永远不可能,因为出于某种原因,ServiceStack 试图将传入的 XML 消息元素绑定到 DTO 的私有字段(由我的服务的元数据页面生成的示例 SOAP 消息 - 注意 "field" "booking" 之后的后缀)。如何使传入消息绑定到 public 属性而不是私有字段?
首先,如果您需要类型化的 C# 服务,我强烈建议您在 C# Add ServiceStack Reference. SOAP is a slow, fragile and bloated serialization format 中使用更具弹性、通用性、更清洁和更快的替代方案,这应该只考虑用于遗留集成。
默认情况下,ServiceStack 使用 .NET XML DataContract Serializer 进行 XML 或 SOAP 序列化,因此行为取决于 .NET 的 XML DataContractSerializer
实现。
为了处理 SOAP,它使用 WCF 的通用 Message
class,默认情况下使用 DataContractSerializer
,但您可以切换为使用 XmlSerializer 填充 WCF 的 Message
通过在您的请求和响应 DTO 中添加 [XmlSerializerFormat] attribute 来实现。
您可以请求 .NET 的 WCF svcutil 使用 /serializer
命令行开关强制生成 DataContract 或 XmlSerializer classes,例如:
svcutil endpoint.wsdl /serializer:DataContractSerializer
svcutil endpoint.wsdl /serializer:XmlSerializer
覆盖内容类型
您可以注册一个 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 Serializer for SOAP Requests 生成的,请求正文是使用 DataContraceSerializer
生成的,因此它不会反映相同的内容如果在 WCF 消息中使用 XmlSerializer 实现,则输出。