FaultException.Detail 返回空

发布于 2024-09-18 10:28:07 字数 1071 浏览 7 评论 0原文

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

我已经成功完成了多次,这次的不同之处在于,错误被声明为数组,正如您可以从抛出异常的方法顶部声明的服务引用属性中看到的那样:

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

看起来详细信息部分根本没有出现!

I am trying to catch a given FaultException on a WCF client. I basically need to extract a inner description from the fault class so that I can then package it in another exception for the upper layers to do whatever.

I've done this successfully a number of time, what makes it different this time is that fault is declared as an array, as you can see from the service reference attribute declared on top of the method that throws the exception:

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

This is my code:

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

Problem is Detail (which is an array) is always coming back empty in the code even if I can see the data (description field etc.) in the SOAP response from WCF trace.

So the stuff I need is definitely coming back but for some reason either it doesn't get deserialized or I can't get to it from code.

Any help appreciated!

UPDATE:

Trying with @Darin suggestion but no luck, the string I am extracting from the XmlReader is "/r/n":

var sb = new StringBuilder();

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

var detail = sb.ToString();

Looks like the detail section is not coming up at all!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

饮惑 2024-09-25 10:28:07

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

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

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

I found the solution on a UPS Forum :

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

"The problem was the visual studio didn't quite map out the ErrorDetail objects right. The ErrorDetail node is called "ErrorDetail", but the type generated for it is "ErrorDetailType." I edited the reference.cs class generated for each service I was using and added a TypeName:"

ら栖息 2024-09-25 10:28:07

很难说问题出在哪里,但我怀疑确凿的证据是该轴 Web 服务没有生成标准消息。解决此问题的一种方法是自己解析 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.
    }
}

It is difficult to say where the problem is but I suspect the smoking gun is this axis web service not generating standard message. One way to workaround this would be to parse the XML yourself:

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.
    }
}
云柯 2024-09-25 10:28:07

我花了很长时间才弄清楚如何从 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() 似乎获得了全部内容,包括新行,这就是我想要的。

It took me ages to figure out how to get the full details message from a FaultException as a string. I eventually figured it out and wrote this extension method:

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

Originally I was using reader.Value but that only appeared to the return the first line of a multi-line details message. reader.ReadContentAsString() appears to get the whole thing, new lines included, which is what I wanted.

浴红衣 2024-09-25 10:28:07

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

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

I came up with the simplest test case I could. I hope it will help you.
Server side:

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

Client side:

try
{
    using (var client = new Service1Client())
    {
        client.Crash();
    }
}
catch(FaultException<FaultClass[]> e)
{
    //Break here
}
要走就滚别墨迹 2024-09-25 10:28:07

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

I had a similar situation in trying to communicate data with faults (specifically a stack trace). See this question. I ended up solving it by creating my own serializable stack trace and including it in a derived FaultException class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文