Как настроить сериализацию WCF XML

У нас есть существующий интерфейс веб-службы SOAP, который мы хотим реализовать с помощью WCF для нового приложения. Кажется, все работает нормально, за исключением одной маленькой детали. Пространство имен XML возвращаемого типа функции должно отличаться от пространства имен XML самой веб-службы. И хоть убей, я не могу заставить его работать.

Я воссоздал ту же проблему на небольшом примере проекта. Интерфейс WCF:

[XmlSerializerFormat]
[ServiceContract(Namespace = "urn:outer-namespace")]
public interface IService1
{
    [OperationContract]
    MyClass DoStuff(int value);
}

[Serializable]
public class MyClass
{
    [XmlElement(ElementName = "DataString")]
    public string MyString { get; set; }
}

Реализация веб-сервиса:

    public class Service1 : IService1
{
    public MyClass DoStuff(int value)
    {
        return new MyClass { MyString = "Wooh!" };
    }
}

Затем ответ от этого веб-сервиса сериализуется как: (Без материалов SOAP)

  <DoStuffResponse xmlns="urn:outer-namespace">
     <DoStuffResult>
        <DataString>Wooh!</DataString>
     </DoStuffResult>
  </DoStuffResponse>

Но мы хотим, чтобы ‹DoStuffResult› имел xmlns = "urn: inner-namespace".

Я пробовал добавить [return: XmlElement (...)] в функцию интерфейса или функцию веб-службы, но этого не произошло. Также не работают [XmlType] или [XmlRoot] в определении класса MyClass.

Кто-нибудь знает, как изменить сериализованное пространство имен XML (или имя элемента) объекта, который является возвращаемым значением функции веб-службы WCF?


person Jeroen-bart Engelen    schedule 16.03.2009    source источник


Ответы (2)


Определите пространства имен с помощью атрибутов определения XML-сериализации (или, лучше) контракта данных.

например с сериализацией XML:

[Serializable, XmlRoot(namespace="http://example.com/eg1")]
public class MyClass {
  [XmlElement(ElementName = "DataString")]
  public string MyString { get; set; }
}

например с сериализацией контракта данных:

[DataContract(Namespace="http://example.com/eg2")]
public class MyClass {
  [DataMember]
  public string MyString { get; set; }
}

РЕДАКТИРОВАТЬ

Исходя из первого комментария, приведенное выше не будет работать, потому что желательно установить пространство имен в оболочке SOAP вокруг сообщения, а не в самом сообщении.

OperationContractAttribute не предлагает никакого контроля над пространствами имен, и я не вижу никаких других атрибутов WCF на уровне метода.

Две возможности: (1) У вас может быть достаточно контроля, отказавшись от уровня абстракции и используя контракт сообщения. (2) Получите текущий WSDL для службы (используя svcutil.exe), вручную настроив его для получения нужных пространств имен, а затем снова используя svcutil.exe для генерации кода, и посмотрите на полученный код.

person Richard    schedule 16.03.2009
comment
Как я уже сказал в вопросе, я попытался добавить атрибут XmlRoot, и это не сработало. Он добавляет пространство имен только к полям в MyClass, но не к самому MyClass. DataContract также не работает, и я предпочитаю XmlSerializer, потому что переименование и порядок не важны. - person Jeroen-bart Engelen; 17.03.2009
comment
Я использовал svcutil, но без указания сериализатора, и он сгенерировал комбинацию MessageContract и ServiceContract с XmlSerializer. Таким образом, у него есть одна или две оболочки, и я все еще могу использовать атрибуты XML, чтобы все это работало. - person Jeroen-bart Engelen; 18.03.2009

После нескольких дней поиска и опробования десятков рекомендованных решений; Я наконец смог заставить WCF прекратить принудительное добавление имени контейнера-оболочки Result к имени метода веб-службы. Хитрость заключалась в том, чтобы добавить в интерфейс веб-службы следующий атрибут декоратора:

[return:MessageParameter(Name = "whatIWantItNamed")]

Этот атрибут должен быть размещен / расположен непосредственно после атрибута [OperationContract] (и непосредственно перед фактической заглушкой метода) в интерфейсе.

(Мне также нужно было добавить атрибут XmlSerializerFormat ко всем атрибутам ServiceContract и OperationContract.)

person Rich Bayless    schedule 20.03.2017