从WCF FaultException响应中提取详细信息

时间:2013-05-13 13:33:05

标签: c# wcf faultcontract

我成功地使用了第三方肥皂服务。我已经为自动生成类的soap Web服务添加了服务引用。

发生错误时,会返回如下的soap响应:

<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 个答案:

答案 0 :(得分:12)

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

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

然而,您可以访问XML并读取innerXml值:

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

这接近有效。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

我发现了几种从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);
}

示例输出:

  

组织不存在。

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

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

示例输出:

  

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

将所有内容的字符串内容作为XML字符串获取

<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>

示例输出:

var pointer = obj;
for ( key of keysArray) { pointer = pointer[key]} ;
console.log(pointer);

答案 3 :(得分:0)

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

catch (FaultException<string> ex)
{
    string yourDetail = ex.Detail;
}