WCF - 反序列化时忽略MessageContract成员(MessageBodyMember)

时间:2016-10-06 08:35:36

标签: wcf soap deserialization

我正在使用SOAP服务,并成功接收响应。

不幸的是,WCF没有对响应POCO的成员进行反序列化。

使用诊断跟踪,我在响应中为每个成员发生以下错误:

Description     An unrecognised element was encountered in the XML during deserialisation which was ignored.
Element         :partnerId

请问你能看到我错在哪里吗?

以下是代码:

服务合同

[ServiceContract(Namespace = "https://foo.com/services/mediationV1/", ConfigurationName = "IPlatformPortType")]
public interface IPlatformPortType
{
    [OperationContract(Action = "https://foo.com/services/foo_bar_HeartBeatV1/", ReplyAction = "*")]
    HeartBeatResponse SendHeartBeat(HeartbeatRequest request);
}

POCO请求

[MessageContract(IsWrapped = true,
    WrapperName = "foo_bar_HeartBeatRequest",
    WrapperNamespace = "https://foo.com/schemas/fooV1/")]
public class HeartbeatRequest
{
    [MessageBodyMember(Namespace = "https://foo.com/schemas/fooV1/", Order = 0)]
    public string transactionId { get; set; }

    [MessageBodyMember(Namespace = "https://foo.com/schemas/fooV1/", Order = 2)]
    public string partnerId { get; set; }
}

SOAP请求

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
    <s:Header>
        <a:Action s:mustUnderstand="1">https://foo.com/services/foo_bar_HeartBeatV1/</a:Action>
        <a:MessageID>urn:uuid:73efa49e-f2b3-4f5d-b750-6784b1becfbc</a:MessageID>
        <a:ReplyTo>
            <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
        </a:ReplyTo>
    </s:Header>
    <s:Body>
        <foo_bar_HeartBeatRequest xmlns="https://foo.com/schemas/fooV1/">
            <transactionId>f642df34-d328-4d76-9a9f-3cf64bdef71d</transactionId>
            <partnerId>bob</partnerId>
        </foo_bar_HeartBeatRequest>
    </s:Body>
</s:Envelope>

POCO回复

[MessageContract(IsWrapped = true,
    WrapperName = "foo_bar_HeartBeatResponse",
    WrapperNamespace = "https://foo.com/schemas/fooV1/")]
public class HeartBeatResponse
{
    [MessageBodyMember(Namespace = "https://foo.com/schemas/fooV1/", Order = 2)]
    public string transactionId { get; set; }

    [MessageBodyMember(Namespace = "https://foo.com/schemas/fooV1/", Order = 3)]
    public int requestStatus { get; set; }
}

SOAP响应

<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
    <soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
        <wsa:MessageID>urn:uuid:b66497fd-4e95-458c-8772-c8bfc0decb51</wsa:MessageID>
        <wsa:Action>urn:mediateResponse</wsa:Action>
        <wsa:RelatesTo>urn:uuid:73efa49e-f2b3-4f5d-b750-6784b1becfbc</wsa:RelatesTo>
    </soapenv:Header>
    <soapenv:Body>
        <ns:foo_bar_HeartBeatResponse xmlns:ns="https://foo.com/schemas/fooV1/">
            <transactionId>f642df34-d328-4d76-9a9f-3cf64bdef71d</transactionId>
            <requestStatus>1</requestStatus>
        </ns:foo_bar_HeartBeatResponse>
    </soapenv:Body>
</soapenv:Envelope>

更新

根据@ TomRedfern的评论,我尝试使用DataContract交换所有MessageContract属性。

不幸的是,这使我无法通知seriliaser POCO是包装器,导致SOAP看起来如下所示:

<s:Body>
    <SendHeartBeat xmlns="https://foo.com/services/fooV1/">
        <request xmlns:b="https://foo.com/schemas/fooV1/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <b:transactionId>7085587a-4275-49ad-9aa9-5b413afcbe62</b:transactionId>
            <b:partnerId>bob</b:partnerId>
        </request>
    </SendHeartBeat>
</s:Body>

请注意,节点的名称现在是Operation(SendHeartBeat)的名称,它的子节点是该操作的参数名称。

我无法控制WSDL,所以这不起作用。

1 个答案:

答案 0 :(得分:0)

经过一天的试验和错误尝试后,我终于让反序列化工作正常。

对于 POCO成员的每个,我做了以下事情:

  • 添加XmlElementAttribute。
  • 将Form参数添加到XmlElementAttribute,值为XmlSchemaForm.Unqualified。
  • 从MessageBodyMemberAttribute中删除Namespace参数并添加到XmlElementAttribute。
  • 删除了MessageBodyMemberAttribute中的所有现有参数。

以下是正确的响应POCO:

[MessageContract(IsWrapped = true,
    WrapperName = "foo_bar_HeartBeatResponse",
    WrapperNamespace = "https://foo.com/schemas/fooV1/")]
public class HeartBeatResponse
{
    [MessageBodyMember]
    [XmlElement(Form = XmlSchemaForm.Unqualified, Namespace = "https://foo.com/schemas/fooV1/")]
    public string transactionId { get; set; }

    [MessageBodyMember]
    [XmlElement(Form = XmlSchemaForm.Unqualified, Namespace = "https://foo.com/schemas/fooV1/")]
    public int requestStatus { get; set; }
}