10

我试图在 WCF 客户端上捕获给定的 FaultException。我基本上需要从故障类中提取一个内部描述,以便我可以将它打包到另一个异常中,以便上层执行任何操作。

我已经成功完成了很多次,这次的不同之处在于,fault 被声明为一个数组,正如您从在引发异常的方法之上声明的服务引用属性中看到的那样:

[System.ServiceModel.FaultContractAttribute(typeof(FaultClass[]), Action = "http://whatever/", Name = "whateverBusinessFault")] 

这是我的代码:

try
{
  // call service here
}
catch (FaultException<FaultClass[]> ex)
{
  if (ex.Detail != null && ex.Detail.Length > 0)
  {
    throw new CustomException(ex.Detail[0].description);
  }
  else
  {
    throw;
  }
}

问题是细节(它是一个数组)总是在代码中返回空,即使我可以在 WCF 跟踪的 SOAP 响应中看到数据(描述字段等)。

所以我需要的东西肯定会回来,但由于某种原因,它要么没有被反序列化,要么我无法从代码中得到它。

任何帮助表示赞赏!

更新

尝试@Darin 建议但没有运气,我从 XmlReader 中提取的字符串是“/r/n”:

var sb = new StringBuilder();

using (XmlReader reader = fault.GetReaderAtDetailContents())
{
  while (reader.Read())
     sb.AppendLine(reader.ReadOuterXml()); 
}

var detail = sb.ToString();

看起来细节部分根本没有出现!

4

5 回答 5

10

我在 UPS 论坛上找到了解决方案:

https://developerkitcommunity.ups.com/index.php/Special:AWCforum/st/id371

“问题是 Visual Studio 没有完全正确地映射 ErrorDetail 对象。ErrorDetail 节点称为“ErrorDetail”,但为其生成的类型是“ErrorDetailType”。我编辑了为每个服务生成的 reference.cs 类正在使用并添加了一个 TypeName:”

于 2016-09-15T17:35:45.093 回答
5

很难说问题出在哪里,但我怀疑确凿的证据是这个轴网络服务没有生成标准消息。解决此问题的一种方法是自己解析 XML:

try
{
    proxy.CallSomeMethod();
}
catch (FaultException ex)
{
    var fault = ex.CreateMessageFault();
    using (XmlReader reader = fault.GetReaderAtDetailContents())
    {
        // TODO: read the XML fault and extract the necessary information.
    }
}
于 2010-09-22T18:36:44.690 回答
3

我花了很长时间才弄清楚如何从FaultException字符串中获取完整的详细信息。我最终想通了并写了这个扩展方法:

public static string GetDetail(this FaultException faultException)
{
    if (faultException == null)
        throw new ArgumentNullException(nameof(faultException));

    MessageFault messageFault = faultException.CreateMessageFault();
    if (messageFault.HasDetail) {
        using (XmlDictionaryReader reader = messageFault.GetReaderAtDetailContents()) {
            return reader.ReadContentAsString();
        }
    }
    return null;
}

最初我正在使用reader.Value,但这似乎只返回了多行详细信息消息的第一行。reader.ReadContentAsString()似乎得到了整个事情,包括新行,这就是我想要的。

于 2016-08-24T16:07:12.797 回答
2

我想出了我能想到的最简单的测试用例。我希望它会帮助你。服务器端:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [FaultContract(typeof(FaultClass[]))]
    string Crash();
}

public class Service1 : IService1
{
    public string Crash()
    {
        var exception = new FaultException<FaultClass[]>(new FaultClass[] { new FaultClass { Data = "TEST" } }, new FaultReason("Boom"));

        throw exception;
    }
}

[DataContract]
public class FaultClass
{
    [DataMember]
    public string Data { get; set; }
}

客户端:

try
{
    using (var client = new Service1Client())
    {
        client.Crash();
    }
}
catch(FaultException<FaultClass[]> e)
{
    //Break here
}
于 2010-09-17T06:00:39.190 回答
1

在尝试与错误(特别是堆栈跟踪)进行数据通信时,我遇到了类似的情况。看到这个问题。我最终通过创建自己的可序列化堆栈跟踪并将其包含在派生的 FaultException 类中来解决它。

于 2011-04-25T03:59:00.143 回答