13

我正在成功地与第三方肥皂服务合作。我添加了对自动生成类的肥皂网络服务的服务引用。

发生错误时,它会返回如下所示的肥皂响应:

<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Body>
      <SOAP-ENV:Fault>
         <faultcode>SOAP-ENV:Client</faultcode>
         <faultstring xsi:type="xsd:string">Error while reading parameters of method 'Demo'</faultstring>
         <detail xsi:type="xsd:string">Invalid login or password. Connection denied.</detail>
      </SOAP-ENV:Fault>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

我可以捕捉到错误但不能提取细节。我尝试了以下代码:

catch (FaultException ex)
{
    MessageFault msgFault = ex.CreateMessageFault();
    var elm = msgFault.GetDetail<string>();
    //throw Detail
}

但是,由于详细节点不是对象,因此会出现以下错误:

Expecting element 'string' from namespace 'http://schemas.datacontract.org/2004/07/MyDemoNamespace'.. Encountered 'Text'  with name '', namespace ''.

这是第三方 API,所以我无法更改响应。

4

5 回答 5

18

消息故障的详细节点应包含 XML。GetDetail 会将此 XML 反序列化为给定对象。

由于内容不是 XML,因此可以使用此方法。

但是,您可以访问 XML 并读取 innerXml 值:

MessageFault msgFault = ex.CreateMessageFault();
var msg = msgFault.GetReaderAtDetailContents().Value;

这种方法奏效了。

于 2013-05-13T13:50:01.747 回答
4

这是我发现的一些方法,可以从中提取详细的异常信息FaultExceptions

获取单个元素的字符串内容

catch (FaultException e)
{
    var errorElement = XElement.Parse(e.CreateMessageFault().GetReaderAtDetailContents().ReadOuterXml());
    var errorDictionary = errorElement.Elements().ToDictionary(key => key.Name.LocalName, val => val.Value);
    var errorMessage = errorDictionary?["ErrorMessage"];
}

示例输出:

组织不存在。

将所有详细信息的字符串内容作为单个字符串获取

catch (FaultException e)
{
    var errorElement = XElement.Parse(e.CreateMessageFault().GetReaderAtDetailContents().ReadOuterXml());
    var errorDictionary = errorElement.Elements().ToDictionary(key => key.Name.LocalName, val => val.Value);
    var errorDetails = string.Join(";", errorDictionary);
}

示例输出:

[ErrorMessage, 组织不存在。];[EventCode, 3459046134826139648];[参数, ]

以 XML 字符串形式获取 Everything 的字符串内容

var errorElement = XElement.Parse(e.CreateMessageFault().GetReaderAtDetailContents().ReadOuterXml());
var xmlDetail = (string)errorElement;

示例输出:

<FaultData xmlns="http://schemas.datacontract.org/2004/07/Xata.Ignition.Common.Contract" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <ErrorMessage>Organization does not exist.</ErrorMessage>
    <EventCode>3459046134826139648</EventCode>
    <Parameters i:nil="true" xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"></Parameters>
</FaultData>
于 2019-07-11T16:35:11.877 回答
2
   public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
    {

        if (reply.IsFault)
        {
            // Create a copy of the original reply to allow default WCF processing
            MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);
            Message copy = buffer.CreateMessage();  // Create a copy to work with
            reply = buffer.CreateMessage();         // Restore the original message 

            MessageFault faultex = MessageFault.CreateFault(copy, Int32.MaxValue); //Get Fault from Message
            FaultCode codigo = faultex.Code;
            //if (faultex.HasDetail)... //More details

            buffer.Close(); 
于 2015-05-13T07:59:01.793 回答
2

下面应该为您提供 FaultException 的详细元素的值。

var faultMessage = faultException.CreateMessageFault();
if(faultMessage.HasDetail){
  Console.Write(faultMessage.GetDetail<XElement>().Value);
}
于 2015-10-30T10:26:28.500 回答
0

您可以 catch FaultException<TDetail>,它免费为您提供详细信息。

catch (FaultException<string> ex)
{
    string yourDetail = ex.Detail;
}
于 2020-07-30T11:50:04.743 回答