2007-12-22

XmlInclude и SoapInclude аттрибуты

Писал давеча Web Service и натолкнулся на баг в платформе .NET. Собственно суть проблемы:

Два класса, базовый и наследник.

public class Foo
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
}

public class Child : Foo {}

Дальше – метод веб службы:

[WebMethod]
public Foo GetFoo()
{
    Foo foo = new Child();
    return foo;
}

Вызываю – вылетает ошибка:
System.InvalidOperationException: There was an error generating the XML document. ---> System.InvalidOperationException: The type Child was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.

Ну, вперёд, в MSDN. Ну, думаю, у меня всё-таки WebService, поэтому решил использовать SoapInclude. Почитал про SoapIncludeAttribute – там даже пример есть. Всё просто, надо только указать этот аттрибут веб методу с указанием типа потомка. Получаем:

[WebMethod]
[SoapInclude(typeof(Child))]
public Foo GetFoo()
{
    Foo foo = new Child();
    return foo;
}

Вызываю метод – индейская народная изба, ФигВам называется. Та же ошибка. Перерыл MSDN, немножко погуглил – никакого результата. Дай думаю попробую XmlIncludeAttribute:

[WebMethod]
[XmlInclude(typeof(Child))]
public Foo GetFoo()
{
    Foo foo = new Child();
    return foo;
}

И о чудо! Заработало. Порылся ещё в Интернете – да, действительно, не я один такой наивный, многие на это напарывались и единственное решение, которое было – именно то, что я изложил – использовать XmlInclude, а не SoapInclude.

Вывод: Майкрософт – редиски. ;)

P.S. Может кто-то знает в чём причина этой проблемы и почему пример из MSDN не работает?

2 comments:

Dmitriy Barday said...

Я смотрю, что у МС целый рассадник этих проблем. Если вернуться к примеру, что я привёл, то при подключении WebReference в клинтском приложении в Refrence.cs будет сгенерированны оба класса. Вопрос, на кой чёрт мне наследник? Я ведь хочу работать только с базовым.
Посмотрел, что мне может помочь в этом случае - аттрибуты XmlType и SoapType. У обоих есть булево свойство - IncludeInSchema. Ну как и следовало ожидать, аттрибут
[SoapType(IncludeInSchema = false)] - не работает. То есть в после Update Web Reference, определение наследника всё ещё остаётся в Refrence.cs
[XmlType(IncludeInSchema = false)] - работает так, как и ожидалось. В Refrence.cs наследника нет.

Alexey Kovyazin said...
This comment has been removed by a blog administrator.