【问题标题】:Multiple name spaces in a soap fault message causing FaultException deserialization to fail肥皂错误消息中的多个名称空间导致 FaultException 反序列化失败
【发布时间】:2010-11-29 07:46:48
【问题描述】:

我们正在连接到 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 的内容。我编写的一些类将序列化非常接近上面的示例,但无法反序列化它,所以我们怀疑存在命名空间问题。

问题:

1 - 你会怎么写这个?

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

[1]:http://www.fiddler2.com/fiddler2/提琴手

【问题讨论】:

标签: .net wcf xml-serialization namespaces wcf-client


【解决方案1】:

我们最终做的是放弃尝试捕获 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);
        }
    }

然后主应用程序使用:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      首先,如果您无法从制作此 Web 服务的人那里获得 WSDL,那么他们就没有业务拥有基于 SOAP 的 Web 服务。无论是否使用“?WSDL”,正确的 WSDL 都可以解决您的问题。

      其次,请贴出eGov2ExceptionType类的代码。我怀疑它没有设置http://eGov.gov 命名空间。

      【讨论】:

      • WSDL 被邮寄给我们是其中之一的“合格合作伙伴”。星期一,我将发布我做过的最接近的课程的代码。
      • 如果你有一个 WSDL,那么你应该能够将它提供给 svcutil.exe 并得到你需要的东西。试试看 svcutil 是否产生任何错误或警告消息。如果没有显示,则查看生成的类 - 有时警告会在生成的代码中显示为 cmets。
      猜你喜欢
      • 2020-01-11
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多