Я понял это (по-видимому, примерно в то же время, что и Джеймс).
Проблема с DataContractSerializer
, и вот контрольный пример, который воспроизводит ее:
class Program
{
static void Main(string[] args)
{
XNamespace ns = "http://tempuri.org/";
XElement element =
new XElement(ns + "MyRequest",
new XElement(ns + "ID", 5),
new XElement(ns + "Name", "Test"),
new XElement(ns + "Description", "This is a test"));
DataContractSerializer serializer = new
DataContractSerializer(typeof(MyRequest));
using (XmlReader reader = element.CreateReader())
{
MyRequest request = (MyRequest)serializer.ReadObject(reader);
Console.WriteLine("ID: {0}, Name: {1}, Description: {2}",
request.ID, request.Name, request.Description);
}
Console.ReadLine();
}
[DataContract(Name = "MyRequest", Namespace = "http://tempuri.org/")]
public class MyRequest
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Description { get; set; }
}
}
Если вы запустите это, вы увидите, что оно пусто для свойства Description
.
Это происходит потому, что DataContractSerializer
ожидает, что члены будут в алфавитном порядке. Это прекрасно работает, когда вы используете DataContractSerializer
как для клиента, так и для службы ... не так хорошо, когда вы генерируете XML вручную.
Если вы добавите Order
свойства к атрибутам DataMember
, это будет работать:
[DataContract(Name = "MyRequest", Namespace = "http://tempuri.org/")]
public class MyRequest
{
[DataMember(Order = 0)]
public int ID { get; set; }
[DataMember(Order = 1)]
public string Name { get; set; }
[DataMember(Order = 2)]
public string Description { get; set; }
}
На этот раз он находит Description
и все остальные поля.
Таким образом, чтобы решить проблему, вы можете выполнить одно из следующих действий:
Добавьте Order
аргументы к атрибутам DataMember
, чтобы соответствовать порядку, в котором вы фактически планируете генерировать XML; или
Убедитесь, что вы добавляете элементы в алфавитном порядке (по имени элемента) на стороне клиента.
Мне не особо нравятся эти обходные пути. Они кажутся хакерскими и легко ломаются. Я думаю, что для сервисов POX я бы предпочел использовать XmlSerializer
вместо DataContractSerializer
, так как он менее придирчив к таким вещам, но, похоже, он не работает "из коробки" с webHttpBinding
. Что-то, что стоит исследовать, когда есть больше времени.