代码之家  ›  专栏  ›  技术社区  ›  Tangurena

SOAP错误消息中的多个名称空间导致FaultException反序列化失败

  •  2
  • Tangurena  · 技术社区  · 15 年前

    我们正在连接到一个Web服务,我们返回的错误消息根本没有反序列化,我所能生成的类的任何版本都不会正确反序列化。我们无法控制服务器端的事情。服务器不允许发现,是否添加?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 catch,这意味着我们将丢失正在发送的FaultMessage的内容。我编写的一些类将真正序列化到上面的示例,但未能对其进行反序列化,因此我们怀疑存在名称空间问题。

    问题:

    你怎么写这个?

    2-这是WCF的常见错误/问题吗?

    〔1〕: http://www.fiddler2.com/fiddler2/ 小提琴手

    3 回复  |  直到 15 年前
        1
  •  4
  •   Tangurena    15 年前

    我们最终做的是放弃试图抓住 故障 然后把它传回SOAP通道。相反,我们创建了一个自定义异常,并将 消息检查器 观察错误并将其作为异常抛出。

    (消毒)代码的相关部分:

       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);
            }
        }
    

    然后,主应用程序使用:

    捕获(egovexception ex)
    {
    //在此处处理异常。
    }

    试图更正名称空间浪费了太多时间。谢谢你的回答。

        2
  •  1
  •   Maurice    15 年前

    如果序列化完全失败,处理此问题的一种方法是使用 Message 输入和输出。这样,您可以在iffault==true时手动解析XML,或者在没有发生错误时使用getBody()获取常规内容。

        3
  •  1
  •   John Saunders    15 年前

    首先,如果您无法从生成此Web服务的人员那里获得WSDL,那么他们就没有业务拥有基于SOAP的Web服务。一个合适的WSDL可以解决您的问题,无论是否?“WSDL”被使用。

    第二,请张贴 eGov2ExceptionType 班级。我怀疑它没有 http://eGov.gov 在其上设置了命名空间。