如何在 MessageContract 类型中使用 XML 属性?

Posted

技术标签:

【中文标题】如何在 MessageContract 类型中使用 XML 属性?【英文标题】:How do I use an XML attribute in a MessageContract type? 【发布时间】:2014-09-19 20:01:25 【问题描述】:

预先说明:我无法更改传入的 SOAP 请求的格式,因为它们是由国际标准 (weeeeeeeeee) 固定的。

我的 WCF 服务中有一个 SOAP 请求,看起来像这样:

<s:Body>
    <Request version="1.0">
        <data someOtherVersion="1.1">
            ...
        </data>
    </Request>
</s:Body>

到目前为止,我们一直在直接使用 System.ServiceModel.Channels.Message 对象,这有点痛苦。我们正在尝试使用如下所示的强类型:

[MessageContract(IsWrapped = false)]
public class Request

    [MessageBodyMember]
    [XmlAttribute("version")]
    public string Version;

    [MessageBodyMember]
    [XmlElement("data")]
    public SomeOtherType Data;


[MessageContract(IsWrapped = false)]
public class Response

    [MessageBodyMember]
    [XmlAttribute("version")]
    public string Version;

    [MessageBodyMember]
    [XmlElement("data")]
    public SomeOtherType ResponseData;


[ServiceContract]
[XmlSerializerFormat]
public interface Service

    [OperationContract(Action = "request", ReplyAction = "response")]
    Response ServiceOperation(Request req);

不幸的是,当我们尝试启动时,我们收到一条错误消息“System.ServiceModel.dll 中发生了类型为 'System.InvalidOperationException' 的未处理异常

附加信息:XmlSerializer 属性 System.Xml.Serialization.XmlAttributeAttribute 在版本中无效。当 IsWrapped 为 false 时,MessageContract 中仅支持 XmlElement、XmlArray、XmlArrayItem 和 XmlAnyElement 属性。"

有趣的是,将“IsWrapped”设置为 true 会产生相同的错误。有没有办法在消息契约类型中序列化 XML 属性,或者在这里使用包装器是我们唯一的选择?

【问题讨论】:

您找到解决方案了吗?我正在为完全相同的问题而苦苦挣扎。 不幸的是,@Robin 没有。解决它的唯一方法是创建一个封闭类型,它适用于某些类型的消息,但不适用于其他类型。啊,按照国际标准工作的乐趣。 我遇到了完全相同的问题。我的问题是为某些 php 客户端返回纯元素数组。但是 wcf 总是生成一个容器对象。我已经厌倦了这个=/ 【参考方案1】:

不幸的是,我发现实现这一目标的唯一方法是使用包装类

[MessageContract(IsWrapped = false)]
public class Response

    [MessageBodyMember(Name = "Response", Namespace = "Http://example.org/ns1")]
    public ResponseBody Body  get; set; 

    public Response()


    public Response(ResponseBody body)
    
        Body = body;
    


[XmlType(AnonymousType = true, Namespace = "Http://example.org/ns1")]
public class ResponseBody

    [XmlAttribute(AttributeName = "version")]
    public string Version  get; set; 

    [XmlElement(ElementName = "data", Namespace = "Http://example.org/ns1")]
    [MessageBodyMember]
    public SomeOtherType ResponseData  get; set; 

【讨论】:

尽管我很讨厌它,但这是我们几年前最终做的事情。【参考方案2】:

尝试使用 XmlElement(typeof(data))

【讨论】:

typeof() 需要 type,而不是字符串。 本题与“数据”字段无关。它只是表明请求正文不是空白的。这个问题与在用 MessageContract 属性修饰的类型中包含 XML 属性有关。

以上是关于如何在 MessageContract 类型中使用 XML 属性?的主要内容,如果未能解决你的问题,请参考以下文章

查看 WCF 生成的 SOAP 消息体

数据合约与​​消息合约

WCF中可为空值类型的错误

如何在 WCF 测试客户端 (WcfTestClient.exe) 中指定列表参数?

Visual Studio Mac Streaming BasicHttpBinding不起作用

WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化