【问题标题】:WCF endpoint not serializing XML correctlyWCF 端点未正确序列化 XML
【发布时间】:2015-03-10 22:10:37
【问题描述】:

我在http://localhost:8090/api/Test 有一个 WCF 端点。实现看起来有点像这样:

[OperationContract]
[WebInvoke(
    Method = "POST",
    BodyStyle = WebMessageBodyStyle.Bare,
    UriTemplate = "Test")]
void TestEndpoint(Test test);

我在别处声明了一些数据对象

[DataContract]
public class TestBase
{
    [DataMember(Name = "BaseValue")]
    public string BaseValue { get; set; }
}
[DataContract(Namespace = "")]
public class Test : TestBase
{
    [DataMember(Name = "TestValue")]
    public string TestValue { get; set; }
}

我遇到的问题是,当我调用端点并通过请求正文传递对象数据时,数据仅在我使用 JSON 时正确序列化,而不是在我使用 XML 时。

以下将非常有用。 Test.TestValue == "TestValue" 和 Test.BaseValue == "BaseValue"。

POST http://localhost:8090/api/Test
Content-Type: text/json

{ "TestValue":"Test", "BaseValue": "BaseValue" }

当我执行以下 Test.TestValue == "TestValue" 和 Test.BaseValue == null :(

POST http://localhost:8090/api/Test 
Content-Type: text/xml

<Test>  <TestValue>Test</TestValue>  <BaseValue>Base</BaseValue></Test>

关于我在这里做错了什么有什么想法吗?

【问题讨论】:

    标签: c# xml json wcf


    【解决方案1】:

    首先,你需要把基类和派生类放在同一个命名空间中:

    [DataContract(Namespace = "")]
    public class TestBase
    {
        [DataMember(Name = "BaseValue")]
        public string BaseValue { get; set; }
    }
    

    如果您不这样做,BaseValue 实际上将位于不同的命名空间中,即数据协定序列化程序选择的默认命名空间:

    <Test xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <BaseValue xmlns="http://schemas.datacontract.org/2004/07/ClrNamespace">foo</BaseValue>
        <TestValue>bar</TestValue>
    </Test>
    

    (JSON 没有对象命名空间,所以这不是问题。)

    接下来,BaseValue 必须在 XML 中位于 TestValue 之前,因为 data contract serializer 是顺序敏感的。见Data Member Order:

    数据排序的基本规则包括:

    • 如果数据协定类型是继承层次结构的一部分,则其基类型的数据成员始终排在第一位。

    • 接下来是当前类型的不具有 DataMemberAttribute 属性集的 Order 属性的数据成员,按字母顺序排列。

    • 接下来是具有 DataMemberAttribute 属性集的 Order 属性的任何数据成员。它们首先按 Order 属性的值排序,然后如果某个 Order 值有多个成员,则按字母顺序排列。订单值可能会被跳过。

    通过调用 CompareOrdinal 方法来建立字母顺序。

    (相比之下,JSON 对象属性被定义为unordered,因此DataContractJsonSerializer 不会遇到这种复杂情况。)

    因此,在基类上添加命名空间声明后,可以反序列化以下 XML:

    <Test>  <BaseValue>Base</BaseValue> <TestValue>Test</TestValue>  </Test>
    

    【讨论】:

    • 我曾尝试将命名空间添加到 TestBase,然后再发布相同的结果。我不知道 XML 顺序对此有任何影响。你让我很快乐!谢谢。
    猜你喜欢
    • 1970-01-01
    • 2011-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多