HttpClient 不报告从 Web API 返回的异常

Posted

技术标签:

【中文标题】HttpClient 不报告从 Web API 返回的异常【英文标题】:HttpClient doesn't report exception returned from web API 【发布时间】:2012-08-24 06:06:19 【问题描述】:

我正在使用 HttpClient 调用我的 MVC 4 Web api。在我的 Web API 调用中,它返回一个域对象。如果出现任何问题,将在服务器上抛出 HttpResponseException,并带有自定义消息。

 [System.Web.Http.HttpGet]
  public Person Person(string loginName)
    
        Person person = _profileRepository.GetPersonByEmail(loginName);
        if (person == null)
            throw new HttpResponseException(
      Request.CreateResponse(HttpStatusCode.NotFound, 
                "Person not found by this id: " + id.ToString()));

        return person;
    

我可以使用 IE F12 在响应正文中看到自定义的错误消息。但是,当我使用 HttpClient 调用它时,我没有收到自定义错误消息,只有 http 代码。对于 404,“ReasonPhrase”始终为“未找到”,对于 500 代码,始终为“内部服务器错误”。

有什么想法吗?如何从 Web API 发回自定义错误消息,同时保持正常返回类型作为我的域对象?

【问题讨论】:

您使用的是什么网络服务器,IIS 还是 ASP.NET 网络服务器? 我在 Win 2008 R2 上使用 IIS。同样,当我使用浏览器调用它时没问题。 【参考方案1】:

(将我的答案放在这里以获得更好的格式)

是的,我看到了,但是 HttpResponseMessage 没有 body 属性。我自己想通了:response.Content.ReadAsStringAsync().Result;。示例代码:

public T GetService<T>( string requestUri)

    HttpResponseMessage response =  _client.GetAsync(requestUri).Result;
    if( response.IsSuccessStatusCode)
    
        return response.Content.ReadAsAsync<T>().Result;
    
    else
    
        string msg = response.Content.ReadAsStringAsync().Result;
            throw new Exception(msg);
    
 

【讨论】:

您应该警惕直接从ReadAsAsync&lt;T&gt; 调用Result,因为这可能会导致间歇性线程问题。相反,请尝试:var contentTask = response.Content.ReadAsAsync&lt;T&gt;();,然后是 contentTask.Wait();,然后是 return contentTask.Result; @Sixto:您能描述一下线程问题吗? Result 文档说“此属性的 get 访问器确保异步操作在返回之前完成。”听起来像是内置了对Wait 的调用。 为什么人们会这样做:response.Content.ReadAsAsync().Result ... 任务还没有完成 Result 将永远为 null ... jeez @Calvin 我无法以这种方式捕获请求超时异常。您能否确认它是否适用于请求超时场景。【参考方案2】:

我在从响应中获取异常时考虑了一些逻辑。

这使得提取异常、内部异常、内部异常 :) 等变得非常容易

public static class HttpResponseMessageExtension

    public static async Task<ExceptionResponse> ExceptionResponse(this HttpResponseMessage httpResponseMessage)
    
        string responseContent = await httpResponseMessage.Content.ReadAsStringAsync();
        ExceptionResponse exceptionResponse = JsonConvert.DeserializeObject<ExceptionResponse>(responseContent);
        return exceptionResponse;
    


public class ExceptionResponse

    public string Message  get; set; 
    public string ExceptionMessage  get; set; 
    public string ExceptionType  get; set; 
    public string StackTrace  get; set; 
    public ExceptionResponse InnerException  get; set; 

如需完整讨论,请参阅this blog post。

【讨论】:

【参考方案3】:

自定义错误消息将在响应的“正文”中。

【讨论】:

是的,我看到了,但是 HttpResponseMessage 没有 body 属性。我自己想通了:response.Content.ReadAsStringAsync().Result;。示例代码: public T GetService(string requestUri) HttpResponseMessage response = _client.GetAsync(requestUri).Result; if(response.IsSuccessStatusCode) return response.Content.ReadAsAsync().Result; else string msg = response.Content.ReadAsStringAsync().Result;抛出新异常(味精); 其实body就是响应的内容。

以上是关于HttpClient 不报告从 Web API 返回的异常的主要内容,如果未能解决你的问题,请参考以下文章

从 ASP.net 4 Web API 2 项目通过 HttpClient 调用 REST 服务导致异常

Angular 5 GET data with Observable and HttpClient - 从 Web API 获取数据

无法使用 HttpClient 对 ASP.NET Web Api 服务进行身份验证

IIS 服务器上的 Web API 内的 Httpclient GetAsync 失败(503 服务不可用)

控制台应用程序 HttpClient 发布到 mvc web api

如何使用 HttpClient 在 Web api 中传递标头值