我对我们向客户返回错误的方式表示担忧 .
我们在收到错误时抛出HttpResponseException会立即返回错误:
public void Post(Customer customer)
{
if (string.IsNullOrEmpty(customer.Name))
{
throw new HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest)
}
if (customer.Accounts.Count == 0)
{
throw new HttpResponseException("Customer does not have any account", HttpStatusCode.BadRequest)
}
}
或者我们累积所有错误然后发送回客户端:
public void Post(Customer customer)
{
List<string> errors = new List<string>();
if (string.IsNullOrEmpty(customer.Name))
{
errors.Add("Customer Name cannot be empty");
}
if (customer.Accounts.Count == 0)
{
errors.Add("Customer does not have any account");
}
var responseMessage = new HttpResponseMessage<List<string>>(errors, HttpStatusCode.BadRequest);
throw new HttpResponseException(responseMessage);
}
这只是一个示例代码,验证错误或服务器错误无关紧要,我只想了解最佳实践,每种方法的优缺点 .
11 回答
如果您使用的是ASP.NET Web API 2,最简单的方法是使用ApiController Short-Method . 这将导致BadRequestResult .
对于那些modelstate.isvalid为false的错误,我通常会发送错误,因为它是由代码抛出的 . 对于正在使用我的服务的开发人员来说,它很容易理解 . 我通常使用下面的代码发送结果 .
这会以下面的格式将错误发送给客户端,这基本上是一个错误列表:
ASP.NET Web API 2真正简化了它 . 例如,以下代码:
在找不到该项时,将以下内容返回给浏览器:
建议:除非发生灾难性错误(例如,WCF故障异常),否则不要抛出HTTP Error 500 . 选择一个代表数据状态的相应HTTP状态代码 . (参见下面的apigee链接 . )
链接:
Exception Handling in ASP.NET Web API(asp.net)和
RESTful API Design: what about errors?(apigee.com)
使用内置的“InternalServerError”方法(在ApiController中可用):
对我来说,我通常会发回
HttpResponseException
并根据抛出的异常相应地设置状态代码,如果异常是致命的,将确定我是否立即发回HttpResponseException
.在一天结束时,它发送回应用而不是视图的API,所以我认为可以将带有异常和状态代码的消息发送给消费者 . 我目前不需要累积错误并将其发回,因为大多数异常通常是由于不正确的参数或调用等 .
我的应用程序中的一个示例是,有时客户端会询问数据,但没有任何数据可用,所以我抛出一个自定义的noDataAvailableException并让它冒泡到web api应用程序,然后在我的自定义过滤器中捕获它发送回相关的消息以及正确的状态代码 .
我不是百分之百确定这是什么最好的做法,但这对我来说是有用的,所以我正在做什么 .
Update :
自从我回答了这个问题后,就这个话题撰写了几篇博文:
http://weblogs.asp.net/fredriknormen/archive/2012/06/11/asp-net-web-api-exception-handling.aspx
(这个在夜间版本中有一些新功能)http://blogs.msdn.com/b/youssefm/archive/2012/06/28/error-handling-in-asp-net-webapi.aspx
Update 2
更新到我们的错误处理过程,我们有两种情况:
对于未找到的常规错误或传递给操作的无效参数,我们返回HttpResponseException以立即停止处理 . 另外,对于我们操作中的模型错误,我们将模型状态字典交给
Request.CreateErrorResponse
扩展并将其包装在HttpResponseException中 . 添加模型状态字典会生成响应正文中发送的模型错误列表 .对于更高层中发生的错误,服务器错误,我们让异常气泡到Web API应用程序,这里我们有一个全局异常过滤器查看异常,用elmah和trys记录它以理解它设置正确在HttpResponseException中再次将http状态代码和相关的友好错误消息作为正文 . 对于我们不期望的异常,客户端将收到默认的500内部服务器错误,但由于安全原因会收到通用消息 .
Update 3
最近,在拿起Web API 2之后,为了发回一般错误,我们现在使用IHttpActionResult接口,特别是System.Web.Http.Results命名空间中的内置类,如NotFound,BadRequest,当它们适合时,如果它们不是我们扩展它们,例如带有响应消息的未发现结果:
只是为了更新ASP.NET WebAPI的当前状态 . 该接口现在称为
IActionResult
,实现没有太大变化:看起来你的验证比错误/异常更麻烦,所以我会说两点 .
Validation
控制器操作通常应采用输入模型,其中验证直接在模型上声明 .
然后,您可以使用
ActionFilter
自动将valiation消息发送回客户端 .有关此检查的更多信息http://ben.onfabrik.com/posts/automatic-modelstate-validation-in-aspnet-mvc
Error handling
最好将消息返回给客户端,代表发生的异常(带有相关的状态代码) .
开箱即用,如果要指定消息,则必须使用
Request.CreateErrorResponse(HttpStatusCode, message)
. 但是,这会将代码绑定到Request
对象,您不应该这样做 .我通常创建自己的“安全”异常类型,我希望客户端知道如何处理并用通用500错误包装所有其他异常 .
使用动作过滤器来处理例外情况如下:
然后你可以在全球注册它 .
这是我的自定义异常类型 .
我的API可以抛出的示例异常 .
您可以在Web Api中使用自定义ActionFilter来验证模型
}
在webApiConfig.cs中注册CustomAttribute类config.Filters.Add(new DRFValidationFilters());
Build
Manish Jain
的答案(适用于简化事物的Web API 2):1)使用 validation structures 响应尽可能多的验证错误 . 这些结构也可用于响应来自表单的请求 .
2) Service layer 将返回
ValidationResult
s,无论操作是否成功 . 例如:3) API Controller 将根据服务功能结果构建响应
一种选择是将几乎所有参数都置为可选参数,并执行自定义验证,以返回更有意义的响应 . 另外,我注意不要让任何例外超出服务范围 .
你可以抛出一个HttpResponseException
对于Web API 2,我的方法始终返回IHttpActionResult,所以我使用...