【问题标题】:Getting error detail from WCF REST从 WCF REST 获取错误详细信息
【发布时间】:2011-01-31 19:04:29
【问题描述】:

我有一个 .Net WCF 客户端使用的 REST 服务。

遇到错误时,REST 服务会返回一个 HTTP 400 错误请求,其响应正文包含 JSON 序列化详细信息。

如果我使用 Fiddler、Javascript 或直接从 C# 执行请求,我可以在发生错误时轻松访问响应正文。

但是,我正在使用具有 6 个非常复杂的接口的 WCF ChannelFactory。这个代理抛出的异常总是ProtocolException,没有有用的细节。

当我收到此错误时,有什么方法可以获取响应正文?


更新

我意识到使用 .Net 有很多不同的方法可以做到这一点,并且还有其他方法可以获得错误响应。知道它们很有用,但不回答这个问题。

我们正在使用的 REST 服务会发生变化,并且当它们发生变化时,复杂的接口会得到更新。将ChannelFactory 与新接口一起使用意味着我们将获得编译时(而不是运行时)异常,并使这些异常更易于维护和更新代码。

在使用 WCF 通道时,有什么方法可以获取错误 HTTP 状态的响应正文?

【问题讨论】:

  • 阅读您的解释,听起来您无法控制 REST 服务本身,对吗?
  • 其实在这种情况下我们是这样做的,但是很难改变。我们的问题是复杂性——WCF ChannelFactory 提供了一种非常好的方法来使用接口来管理它。烦人的是,当 HTTP 标头状态不是 200 时,它会丢弃响应正文。当我们从 REST 服务收到错误时,它会返回 HTTP 400 或 500 状态,正文中包含详细信息。

标签: .net wcf rest channelfactory protocolexception


【解决方案1】:

不要认真使用 ChannelFactory :-)。为什么要创建一个 REST 接口,然后使用 WCF 客户端代理。使用 REST 服务有什么好处?为什么不直接使用 wsHttpBinding? 使用 REST 入门工具包中的 HttpClient 类,您可以发出标准 HTTP 请求,然后使用 DataContractSerializer 反序列化响应。

例如

var httpClient = new HttpClient();
var content = httpClient.Get("http://example.org/customer/45").Content;
var customer = content.ReadAsDataContract<Customer>()

【讨论】:

  • 我喜欢你的简单就是更好的方法,但是我们有大量的接口,几乎所有的方法都需要复杂的 POST 内容。 ChannelFactory 的代理实现的代码简单性为我们节省了大量的代码复杂性。我知道它可以按照你的方式完成,但我真正想知道的是:如果我们以 ChannelFactory 方式执行,我们可以获得错误详细信息吗?
【解决方案2】:

您可以尝试从服务中抛出 WebProtocolException。这样,错误详细信息应包含在 HTTP 响应的正文中。看看这篇文章:

Effective Error Handling with WCF & REST

【讨论】:

  • 这正是服务所做的——在 HTTP 响应正文中序列化为 JSON 的详细信息。问题是 ChannelFactory 抛出了一个异常,没有任何 HTTP 标头状态(除了 200 之外)的详细信息。该服务有效,问题在于 WCF 的客户端实现。
【解决方案3】:

我的两分钱是 WCF 擅长使用许多不同的绑定来公开同一个类。与 C# 通信时,使用擅长异常信息的 SOAP 绑定。如果您必须使用 REST 样式绑定,您可以使用简单的 WebRequest 来调用服务并使用 JSON 序列化程序来反序列化结果。这也可以让您直接访问响应代码。

【讨论】:

    【解决方案4】:

    您可以按如下方式检索异常详细信息:

                    Exception innerException = exception.InnerException;
                    WebException webException = innerException as WebException;
                    HttpWebResponse response = webException.Response as HttpWebResponse;
                    string statusDescription = response.StatusDescription;
                    HttpStatusCode statusCode = response.StatusCode;
    

    【讨论】:

      【解决方案5】:

      user653761 描述的方法对我有用;在访问HttpWebResponse 对象后,我可以像这样使用DataContractSerializer 类:

      var serializer = new DataContractSerializer(typeof(MyDataContractType));
      var deserialized = 
          (serializer.ReadObject(httpWebResponse.GetResponseStream()) as MyDataContractType);
      
      // ...
      

      如果您使用正确的序列化程序,我想这适用于 WCF 可以序列化的任何内容,但尚未测试性能。

      【讨论】:

        【解决方案6】:

        ProtocolExceptionInnerException 将是 WebException。 您可以从中获取HttpWebResponse 并调用GetResponseStream 来读取实际的响应正文。 (请记住在阅读之前寻找到流的开头)。

        var webException = (WebException) protocolException.InnerException;
        var response = (HttpWebResponse) webException.Response;
        var responseStream = response.GetResponseStream()
        responseStream.Seek(0, SeekOrigin.Begin);
        var reader = new StreamReader(responseStream);
        var responseContent = reader.ReadToEnd();
        

        【讨论】:

          猜你喜欢
          • 2011-04-24
          • 1970-01-01
          • 1970-01-01
          • 2012-12-26
          • 2012-06-20
          • 1970-01-01
          • 2022-08-19
          • 1970-01-01
          • 2016-12-23
          相关资源
          最近更新 更多