Веб-служба ASP.Net. Как правильно добавить элемент подробности в ответ об ошибке SOAP, который работает как для SOAP 1.1, так и для SOAP 1.2? - PullRequest
3 голосов
/ 01 июля 2010

Веб-службы ASP.Net 2.0 автоматически создают привязки SOAP 1.1 и SOAP 1.2. Однако наш веб-сервис имеет расширения SOAP и пользовательскую обработку исключений, которые предполагают, что используется только привязка SOAP 1.1 (например, расширение SOAP использует заголовок HTTP SOAPAction для управления поведением).

Я пытаюсь исправить код, который делает эти предположения, и заставить его работать с SOAP 1.1 или SOAP 1.2 должным образом. Я столкнулся с небольшой проблемой при создании элементов для наших ошибок SOAP.

Рассмотрим следующую реализацию веб-метода:

[WebMethod]
public void
ThrowsSoapException()
{
    throw new SoapException("This is a SOAP exception.", SoapException.ServerFaultCode);
}

Вызов этого через SOAP 1.1 дает следующий результат:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:Server</faultcode>
         <faultstring>This is a SOAP exception.</faultstring>
         <detail/>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

Вызов через SOAP 1.2 дает следующий результат:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <soap:Body>
      <soap:Fault>
         <soap:Code>
            <soap:Value>soap:Receiver</soap:Value>
         </soap:Code>
         <soap:Reason>
            <soap:Text xml:lang="en">This is a SOAP exception.</soap:Text>
         </soap:Reason>
         <soap:Detail/>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

В обоих этих случаях в качестве дочернего элемента <soap:Fault> есть пустой элемент detail, но у него другое квалифицированное имя, либо <detail>, либо <soap:Detail>.

Теперь рассмотрим следующий код, который пытается создать SOAPException с элементом detail.

[WebMethod]
public void
ThrowsSoapExceptionWithDetail()
{
    XmlDocument doc = new XmlDocument();
    XmlNode detail =
        doc.CreateNode(XmlNodeType.Element, SoapException.DetailElementName.Name, SoapException.DetailElementName.Namespace);
    XmlNode custom =
        doc.CreateNode(XmlNodeType.Element, "custom", "http://example.com/xml/namespace/blah");
    custom.InnerXml = "Detail value";
    detail.AppendChild(custom);
    throw new SoapException("This is a SOAP exception with a detail element.", SoapException.ServerFaultCode, Context.Request.Url.AbsoluteUri, detail);
}

Ответ SOAP 1.1:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:Server</faultcode>
         <faultstring>This is a SOAP exception with a detail element.</faultstring>
         <faultactor>http://localhost/simplewebservice/service1.asmx</faultactor>
         <detail>
            <custom xmlns="http://example.com/xml/namespace/blah">Detail value</custom>
         </detail>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

и ответ SOAP 1.2:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <soap:Body>
      <soap:Fault>
         <soap:Code>
            <soap:Value>soap:Receiver</soap:Value>
         </soap:Code>
         <soap:Reason>
            <soap:Text xml:lang="en">This is a SOAP exception with a detail element.</soap:Text>
         </soap:Reason>
         <soap:Node>http://localhost/simplewebservice/service1.asmx</soap:Node>
         <detail>
            <custom xmlns="http://example.com/xml/namespace/blah">Detail value</custom>
         </detail>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

Ответ SOAP 1.2 теперь имеет неверное квалифицированное имя для элемента detail. Это должно быть <soap:Detail>, но вместо этого просто <detail>, то же самое, что и ответ SOAP 1.1.

Кажется, что платформа ASP.Net 2.0 сделала немало для преобразования SOAPException в соответствующую форму для версии SOAP, но ей не удалось должным образом обработать элемент detail. Кроме того, похоже, что они не предоставили правильное квалифицированное имя SOAP 1.2 для элемента detail, как это было сделано с помощью свойства SoapException.DetailElementName.

Итак, как правильно добавить элемент подробности в ответ об ошибке SOAP, который работает как для SOAP 1.1, так и для SOAP 1.2? Нужно ли самому определять версию SOAP и жестко кодировать квалифицированное имя SOAP 1.2 для элемента detail?

Ответы [ 3 ]

1 голос
/ 15 декабря 2010

Не представляю, какая часть вашего вопроса связана с кодированием, извините, но есть обходной путь - отключите soap1.2 в вашем файле web.config, если вы еще этого не видели.

....

0 голосов
/ 19 ноября 2015

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

Класс WebService , из которого получен класс веб-службы ASMX, предоставляет свойство SoapVersion , которое содержит версию протокола SOAP, использованного для создания текущего запроса SOAP.

Детальный раздел, соответствующий текущей версии SOAP, может быть легко создан.

using System.Xml.Linq;

XNamespace detailElementNamespace;
string detailElementName;
if (soapVersion == SoapProtocolVersion.Soap12)
{
    detailElementNamespace = "http://www.w3.org/2003/05/soap-envelope";
    detailElementName = "Detail";
}
else
{
    detailElementNamespace = "";
    detailElementName = "detail";
}

var document = new XmlDocument();
document.LoadXml(
    new XElement(detailElementNamespace + detailElementName,
        new XElement("MySection",
            new XElement("MyCode", "..."),
            new XElement("MyDescription", "...")
            )).ToString());

throw new SoapException(
    "MESSAGE",
    SoapException.ClientFaultCode,
    "ACTOR",
    document.DocumentElement);
0 голосов
/ 01 июля 2010

Следующее описание не является обманом:

Решение этой проблемы - использование WCF.

Это похоже на ошибку в обработке веб-сервисов ASMXэлемента detail в ошибке SOAP 1.2.Очевидно, что нет смысла изменять квалифицированное имя элемента в зависимости от того, имеет ли элемент значение.

Вы можете сообщить об этой ошибке на Connect , но так как только критический ASMXошибки исправляются, это вряд ли поможет вам.

Я сомневаюсь, что WCF имеет эту проблему, так как он полностью поддерживает ошибки SOAP.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...