То, почему делает атрибут XmlRoot, проигнорировано в WCF и как преодолеть это

Мы заметили что, когда мы подвергаем сервис WCF, который использует классы, украшенные различными xml атрибутами сериализации, несмотря на то, что мы используем атрибут XmlSerializerFormat в интерфейсе, любой атрибут XmlRoot на любом из параметров операции полностью проигнорирован. Пространство имен параметров всегда является пространством имен сервиса и не, что мы указываем.

Это вызывает нас проблемы, поскольку это, кажется, не назад совместимо с ASMX и также потому что мы используем BizTalk и должны иметь более трудный контроль над формой обмененного XML's.

Несколько вопросов затем -

  1. Кто-либо знает то, что объяснение позади этого решения?
  2. Кто-либо знает, как это происходит? Я находился под впечатлениями, что WCF, с атрибутом XmlSerializerFormat, использует XmlSerialiser для сериализации типов, которые предложили бы, чтобы XmlRoot был принят во внимание, каким образом дело обстоит не так? (это только вследствие того, что, принимая конверт SOAP во внимание, параметр не является корнем?)
  3. Самое главное - кто-либо знает, существует ли способ 'вызвать проблему' - т.е. заставить параметры быть пространства имен нашего выбора?

Я видел это сообщение, но я не полагаю, что это относится к моему вопросу -

Согласно запросу Wagner Silveira - контракты я раньше тестировал, это -

[ServiceContract(Namespace = "http://servicecontract"),
 XmlSerializerFormat(Style = OperationFormatStyle.Document)]
public interface ITestService
{
    [OperationContract]
    MyOtherType MyTestMethod(MyType obj);
}

// Composite class for DCS and XMLS
[Serializable, XmlType, XmlRoot(Namespace = "http://datacontract")] 
public class MyType
{
    [XmlAttribute]
    public string StringValue { get; set; }
}

// Composite class for DCS and XMLS
[Serializable, XmlType, XmlRoot(Namespace = "http://datacontract")]
public class MyOtherType
{
    [XmlAttribute]
    public string OtherStringValue { get; set; }
}

8
задан Community 23 May 2017 в 12:22
поделиться

2 ответа

Я предполагаю, что вы используете мыло в качестве формата сообщения. В этом случае объект, который вы сериализуете, не является корнем XML, огибающая SOAP. Так что имеет смысл, что Xmlroot будет игнорироваться. По умолчанию WCF создаст контракт на сообщения для вас и назвать ответ, и у него есть пространство пространства имен. То, что вы можете сделать, это Создайте свой собственный договор сообщения , чтобы иметь полный контроль над SOAP.

Создайте следующие два класса:

[MessageContract]
public class MyTestMethodRequest
{
    [MessageBodyMember( Namespace = "http://datacontract" )]
    public MyType MyType;
}

[MessageContract]
public class MyTestMethodResponse
{
    [MessageBodyMember( Namespace = "http://datacontract" )]
    public MyOtherType MyOtherType;
}

затем измените подпись вашей службы операции на следующее.

[OperationContract]
public MyTestMethodResponse MyTestMethod( MyTestMethodRequest request )
{
    return new MyTestMethodResponse {
        MyOtherType = new MyOtherType {
            OtherStringValue = "bar"
        }
    };
}

Теперь, если вы примеры сообщения SOAP, вы должны увидеть следующее:

Запрос

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none"
            s:mustUnderstand="1">http://servicecontract/TestService/MyTestMethod</Action>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <MyTestMethodRequest xmlns="http://servicecontract">
      <MyType StringValue="foo" xmlns="http://datacontract" />
    </MyTestMethodRequest>
  </s:Body>
</s:Envelope>

Ответ

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header />
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <MyTestMethodResponse xmlns="http://servicecontract">
      <MyOtherType OtherStringValue="bar" xmlns="http://datacontract" />
    </MyTestMethodResponse>
  </s:Body>
</s:Envelope>
3
ответ дан 6 December 2019 в 00:07
поделиться

Эта функция была предложена из-за проблем с производительностью на встраиваемых системах при использовании $ .ajax , сообщенных в списке рассылки jQuery-Dev. Появится поток .

В основном они предпочитали вводить и использовать эту единственную пустую функцию, а не объявлять пустые анонимные функции вокруг.

Теперь эта функция используется в модулях ajax , event и offset .

Можно просмотреть commit при его введении.

-121--1102681-

Я вижу только два преимущества для небольших сайтов: 6) RESTful urls, который позволяет SEO. 7) Отсутствие событий ViewState и PostBack (и повышение производительности в целом)

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

Я ясно вижу преимущество MVC на более крупных сайтах с несколькими разработчиками.

-121--653050-

Я не знаю, почему WCF игнорирует StartRoot, поэтому я не могу ответить на эту часть вашего вопроса. Но у меня есть несколько способов решить проблему.

  1. сначала начинается с WSDL.
    Если имеется определенный набор пространств имен XML, которые необходимо применить к отправляемым и получаемым сообщениям, используйте WSDL и XML Schema, чтобы явно указать их.

    Затем создайте код-заглушку на стороне сервера или код прокси на стороне клиента непосредственно из этого WSDL с помощью средства svcutil.exe .

  2. используйте настраиваемый ServiceHost
    Другой вариант, открытый для вас, описанный в по этой ссылке , заключается в использовании настраиваемого ServiceHost, который отменяет решение WCF игнорировать атрибуты GroupRoot или GroupType для типов сообщений.


Если вы решите использовать подход WSDL-First, WSDL должен выглядеть следующим образом:

<?xml version="1.0" encoding="utf-8" ?>

<definitions
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    targetNamespace="urn:The-Service-namespace"
    xmlns:tns="urn:The-Service-namespace"
    xmlns:s="http://www.w3.org/2001/XMLSchema"
    xmlns:n0="urn:The-Request-namespace"
    xmlns:n1="urn:The-Response-namespace"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    elementFormDefault= "unqualified"
  >

    <types>
      <s:schema targetNamespace="urn:The-Request-namespace" >
        <s:complexType name="Type1">
          <s:sequence>
            <s:element name="x" minOccurs="1" maxOccurs="1" type="s:string"/>
          </s:sequence>
        </s:complexType>
        <s:element name="Type1" type="n0:Type1" />
      </s:schema>


      <s:schema targetNamespace="urn:The-Response-namespace" >
        <s:complexType name="Type2">
          <s:sequence>
            <s:element name="x" minOccurs="1" maxOccurs="1" nillable="false" type="s:string"/>
            <s:element name="y" minOccurs="1" maxOccurs="1" nillable="false" type="s:int"/>
            <s:element name="z" minOccurs="1" maxOccurs="1" nillable="false" type="s:boolean" />
          </s:sequence>
        </s:complexType>
        <s:element name="Type2" type="n1:Type2" />
      </s:schema>

    </types>



<message name="RequestMessage">
   <part name="inPart1" element="n0:Type1" />
</message>
<message name="ResponseMessage">
   <part name="outPart1" element="n1:Type2" />
</message>



<portType name="PortTypeName">
  <operation name="Method1">
      <input message="tns:RequestMessage" />
      <output message="tns:ResponseMessage" />
   </operation>
</portType>



<binding name="InterfaceName" type="tns:PortTypeName">
    <soap:binding
       transport="http://schemas.xmlsoap.org/soap/http"
       style="rpc" />

    <operation name="Method1">
        <soap:operation soapAction="" style="document" />
        <input>  <soap:body use="literal" /> </input>
        <output> <soap:body use="literal" /> </output>
    </operation>
</binding>

</definitions>

Этот WSDL очень прост - он определяет одну операцию, с одним сообщением запроса и одним сообщением ответа.

Обратите внимание, что существует три пространства имен xml:

  • urn: The-Service-namespace
    , используемое для элемента, который переносит запрос и ответ - первый элемент внутри < SOAP: body >
  • urn: The-Request-namespace
    , используемый для элемента, обернутого внутри этой оболочки запроса, который десериалиализуализируется в экземпляр Type1.
  • urn: пространство имен ответа
    , используемое для элемента, обернутого внутри этой оболочки ответа, которая десериализируется в экземпляр Type2.

Если интерфейс веб-служб сложнее, имеет больше операций и, следовательно, больше типов сообщений запросов и ответов, можно добавить больше пространств имен, если хотите, для всех этих дополнительных типов.

1
ответ дан 6 December 2019 в 00:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: