2015-03-10 2 views
1

У меня есть конечная точка WCF по адресу http://localhost:8090/api/Test. Реализация выглядит немного как это:Конечная точка WCF не правильно сериализует XML

[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 == нуль :(

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

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

Любые идеи о том, что я делаю неправильно здесь?

ответ

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должен прийти до TestValue в XML, потому что data contract serializer чувствителен к заказу. См Data Member Order:

Основные правила для упорядочения данных включают в себя:

  • Если тип контракта данных является частью иерархии наследования, элементы данных из его базовых типов всегда первые в порядке.

  • Следующие в порядке являются членами данных текущего типа, которые не имеют свойства Order атрибута DataMemberAttribute, в алфавитном порядке.

  • Далее перечислены все члены данных, у которых есть свойство Order атрибута DataMemberAttribute. Они упорядочиваются по значению свойства Order сначала, а затем в алфавитном порядке, если имеется более одного члена определенного значения Order. Значения заказа могут быть пропущены.

Алфавитный порядок устанавливается путем вызова метода CompareOrdinal.

(свойства объекта JSON, в отличии от этого, определяются как unordered, так что вы не встретите это осложнение с DataContractJsonSerializer.)

Таким образом, добавив объявление пространства имен на базовый класс, следующий XML может быть десериализован:

<Test> <BaseValue>Base</BaseValue> <TestValue>Test</TestValue> </Test> 
+1

Я попытался добавить пространство имен в TestBase перед отправкой это с тем же результатом. Я понятия не имел, что порядок XML повлиял на это. Ты сделал мой день! Благодарю. – Melon

Смежные вопросы