Различное поведение сериализатора .NET XML при десериализации отсутствующих целых чисел

Недавно я столкнулся с проблемой веб-службы SOAP, где WSDL указывает целое число для определенного поля, но XML приходит с пустым элементом, из-за чего логика десериализации .NET выдает исключение FormatException.

WSDL выглядит следующим образом:

<xsd:element minOccurs="0" maxOccurs="1" name="TransID" type="xsd:int" />

И SOAP выглядит так:

<TransID></TransID>

Это вызывает исключение при разборе ответа. Сервер, с которым я разговариваю, принадлежит поставщику, поэтому у меня нет возможности его изменить. Я взломаю это в краткосрочной перспективе, переопределив поле как строку.

Мой вопрос заключается в следующем: пытаясь диагностировать эту проблему, я вытащил XML в файл и создал свой собственный XmlSerializer для проверки десериализации с использованием POCO, сгенерированного импортом WSDL. XmlSerializer, который я создал, отлично анализирует этот XML и создает родительский тип, как и ожидалось. Никаких исключений. Значение поля равно нулю, чего и следовало ожидать. Почему десериализатор SOAP рвет, а простой десериализатор, который я создал, работает нормально?


person Kent    schedule 07.11.2012    source источник
comment
Если TransID является целым числом, я бы ожидал, что он будет работать как пустой элемент...   -  person Marc Gravell    schedule 08.11.2012
comment
У меня нет проблем с тем, что он не работает для десериализации. Для десериализатора вполне разумно бросить попытку проанализировать пустую строку как целое число. Вопрос был о различиях в поведении. Но после дополнительного тестирования оказалось, что мой тест десериализации не погружался в поля родительской структуры, поэтому создавалось впечатление, что он успешно десериализовал плохой XML, потому что возвращал объект. Но оказалось, что это не десериализация внутренних полей. Отсюда и разница в поведении.   -  person Kent    schedule 08.11.2012


Ответы (2)


Это нормально и ожидаемо; пустая строка недействительна как целое число и не может быть проанализирована. XmlSerializer ведет себя одинаково:

using System.IO;
using System.Xml.Serialization;

static class Program {
    static void Main() {
        var obj = new XmlSerializer(typeof(Foo)).Deserialize(
            new StringReader("<Foo><TransID></TransID></Foo>"));
    }
}
public class Foo
{
    public int TransID { get; set; }
}
person Marc Gravell    schedule 07.11.2012

IMO, вы должны объявить свою собственность как Nullable:

public int? TransID { get; set; }

Этого должно быть достаточно, чтобы он работал при сериализации и десериализации объекта.

person Rui Jarimba    schedule 15.11.2012