Несколько пространств имен в сообщении ошибки мыла, приводящее к сбою десериализации FaultException - PullRequest
2 голосов
/ 18 сентября 2009

Мы подключаемся к веб-службе, и возвращаемое нами сообщение об ошибке не десериализуется (вообще), и ни одна из версий класса, которые я могу создать, не будет десериализована правильно. У нас нет контроля над серверной стороной вещей. Сервер не разрешает обнаружение, поэтому добавление? WSDL в конец URL-адреса конечной точки приводит к ошибке, а не к WSDL.

[Fiddler] [1] показывает, что возвращаемое сообщение об ошибке выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:eGov="http://eGov.gov" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <soapenv:Fault>
    <faultcode>Client</faultcode>
    <faultstring/>
      <detail>
        <eGov:eGov2Exception>
          <eGov:ErrorClassification>SOME_ERROR</eGov:ErrorClassification>
          <eGov:ErrorCode>SOME_ERROR_CODE</eGov:ErrorCode>
          <eGov:ErrorMessage>Your request was unsuccessful. blah blah blah.</eGov:ErrorMessage>
        </eGov:eGov2Exception>
      </detail>
    </soapenv:Fault>
  </soapenv:Body>
</soapenv:Envelope>

Тем не менее, ни один из созданных нами классов (пробующий xsd.exe, svcutil и другие, включая код, написанный с нуля) не сможет десериализовать его, когда мы попытаемся поймать его с помощью:

catch (FaultException<eGov2ExceptionType> exp)
  {
     // Never stops here. 
  }
catch (FaultException<AllOtherAttemptedClasses> exp)
  {
     // Never stops here. 
  }
catch (SoapException se)
  {
     // Never stops here. 
  }
catch (FaultException exp)
  {
     //Always gets caught here. 
  }

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

Вопросы:

1 - Как бы вы написали это?

2 - Это распространенная ошибка / проблема с WCF?

[1]: http://www.fiddler2.com/fiddler2/ Скрипач

Ответы [ 3 ]

4 голосов
/ 25 сентября 2009

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

Соответствующая часть (санированная) кода:

   public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        if (reply.IsFault)
        {
            XmlDictionaryReader xdr = reply.GetReaderAtBodyContents();
            XNode xn = XDocument.ReadFrom(xdr);
            string s = xn.ToString();
            XDocument xd = XDocument.Parse(s);
            XNamespace nsSoap = "http://schemas.xmlsoap.org/soap/envelope/";
            XNamespace ns = "http://eGov.gov";
            XElement xErrorClass = xd.Element(nsSoap + "Fault").Element("detail").Element(ns + "eGov2Exception").Element(ns + "RequestErrorClassification");
            XElement xErrorCode = xd.Element(nsSoap + "Fault").Element("detail").Element(ns + "eGov2Exception").Element(ns + "RequestErrorCode");
            XElement xErrorMessage = xd.Element(nsSoap + "Fault").Element("detail").Element(ns + "eGov2Exception").Element(ns + "RequestErrorMessage");

            throw new eGovException(xErrorClass.Value, xErrorCode.Value, xErrorMessage.Value);
        }
    }

Затем основное приложение использует:

catch (eGovException ex)
{
// Здесь обрабатывается исключение.
}

Слишком много времени было потрачено впустую, пытаясь исправить пространства имен. Спасибо за ответы.

1 голос
/ 20 сентября 2009

Прежде всего, если вы не можете получить WSDL от людей, создавших этот веб-сервис, у них нет бизнеса, имеющих веб-сервис на основе SOAP. Правильный WSDL решит вашу проблему, независимо от того, используется ли «? WSDL».

Во-вторых, пожалуйста, отправьте код класса eGov2ExceptionType. Я подозреваю, что на нем не установлено пространство имен http://eGov.gov.

1 голос
/ 18 сентября 2009

Один из способов справиться с этим, если сериализация завершается неудачей, - это использовать OoperationContract, используя тип Message в качестве входа и выхода. Таким образом, вы можете вручную проанализировать XML, когда Iffault == true, или использовать GetBody (), чтобы получить обычное содержимое, если не произошло ошибок.

...