2016-03-09 54 views
6

在MVC6 /的WebAPI模板的WebAPI控制器实现返回集合GET方法是这样的动作:从MVC6/WepApi控制器返回错误字符串

[HttpGet] 
public IEnumerable<MyEntity> Get() 
{ 
    //my code to return entities 
} 

假设我的代码返回的结果抛出异常,我将如何向消费者返回错误消息?

据我注意到一个异常会导致HTTP 500.这很好,但我想给调用者一个消息,告诉他出了什么问题。由于模板操作的签名,我无法捕捉异常并返回一些Http ***或ObjectResult实例。

+0

看一看答案为[这里](http://stackoverflow.com/q/31054012/5233410)问题 – Nkosi

回答

10

您将需要自己添加一些代码,以处理错误并返回消息。

一种选择是使用异常过滤器并将其添加到全局或选定的控制器上,尽管此方法仅涵盖来自控制器操作方法的异常。例如,下面的过滤器会返回一个JSON对象只有当要求接受为应用程序/ JSON(否则它会让异常通过其例如可以由全局错误页面处理):

public class CustomJSONExceptionFilter : ExceptionFilterAttribute 
{  
    public override void OnException(ExceptionContext context) 
    { 
     if (context.HttpContext.Request.GetTypedHeaders().Accept.Any(header => header.MediaType == "application/json")) 
     { 
      var jsonResult = new JsonResult(new { error = context.Exception.Message }); 
      jsonResult.StatusCode = Microsoft.AspNetCore.Http.StatusCodes.Status500InternalServerError; 
      context.Result = jsonResult; 
     } 
    } 
} 

services.AddMvc(opts => 
{ 
    //Here it is being added globally. 
    //Could be used as attribute on selected controllers instead 
    opts.Filters.Add(new CustomJSONExceptionFilter()); 
}); 

另一种选择是您可以更改签名以提供更灵活的响应。然后,您可以像通常那样处理错误,然后返回用户友好的错误消息。

public IActionResult Get() { 
    try { 
     IEnumerable<MyEntity> result; 
     //...result populated 
     return new HttpOkObjectResult(result); 
    } catch (Exception ex) { 
     //You should handle the error 
     HandleError(ex);//the is not an actual method. Create your own. 
     //You could then create your own error so as not to leak 
     //internal information. 
     var error = new 
      { 
       message = "Enter you user friendly error message", 
       status = Microsoft.AspNetCore.Http.StatusCodes.Status500InternalServerError 
      }; 
     Context.Response.StatusCode = error.status;    
     return new ObjectResult(error); 
    } 
} 
+1

与您提供的链接一起提供三种可能的方式。我会看到什么最适合。我会接受你的回答! – NicolasR

1

就像你会保持任何程序运行一样。

try { 
    ... 
} catch (Exception e) { 
    return errorMessageView; 
} 

或者,您可以使用HandleErrorAttribute

+0

谢谢,但我觉得我没”不够清楚。我正在编写一个API,所以我不想返回一个视图。客户端应该检查Http OK(200)或500(内部错误)。如果客户端有500个,他应该能够显示错误信息。如何从异常处理程序向客户端收到此错误消息?搜索HandleErrorAttribute我发现HttpResponseException,但这似乎不支持在MVC 6中。 – NicolasR

+0

您可以返回JSON'{'result':'error','status',500}'? – will

+0

只有当我更改return语句但感觉不自然时,因为控制器模板始终创建Get操作并返回集合。从别人的建议看来,最好的方法是让异常通过并实现过滤器或错误中间件。 – NicolasR

3

改变你的方法看起来像

[HttpGet] 
[ResponseType(typeof(IEnumerable<MyEntity>))] 
public IHttpActionResult Get() 
{ 
    //when ok 
    return Ok(response); // response is your IEnumerable<MyEntity> 

    //when error 
    throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.WhateverStatusCodeSuitable) 
      { 
       ReasonPhrase = "your message" 
      }); 

} 
+2

看起来不错,但正如在这篇文章中解释http://stackoverflow.com/questions/31054012/asp-net-5-mvc-6-equivalent-of-httpexception?lq=1 HttpResponseException不再可用。 – NicolasR

0

你可以有例外浪费时间,但我得到我们不应该以任何更多这样想的印象。这似乎是MVC6的禅:

[HttpGet("{id}")] 
    [ProducesResponseType(typeof(IEnumerable<string>), 200)] 
    [ProducesResponseType(typeof(void), 404)] 
    public IActionResult Get(int id) 
    { 
     Product product = null; 
     if (!this.productRepository.TryGet(id, out product)) 
     { 
      return NotFound(); 
     } 

     return Ok(product); 
    } 
+0

如果只是发现或未找到,然后确定。但是,在现实情况下发生的所有实际异常(如破损的数据库,不可用的嵌套服务以及不要忘记程序员引入的错误)​​的情况呢?我同意IActionResult会给我自由返回任何需要的东西,但这意味着我必须在每个控制器方法中捕获异常,以将其转换为“发生错误,请参考...”(作为最小值)。 – NicolasR

+0

无论您是否喜欢,所有这些例外都会变成一种或另一种形式的HTTP结果。国际海事组织正在抓住这一范例,而不是假设某种例外实际上传回给客户。 –

+0

我同意你关于这个范例的看法,并且使用你在我的大多数方法中发布的代码。另一方面,查看Nkosi答案中的第二个代码片段。我真的不想在我的每个控制器中都有这样的代码。我的问题是,默认异常处理程序只返回代码500到客户端没有任何错误文本。这就是我喜欢CustomExceptionFilter解决方案的原因。 – NicolasR