当前位置: 首页 > 知识库问答 >
问题:

在ASP.NET Web API中返回错误的最佳实践

郭华美
2023-03-14

我担心我们返回错误给客户的方式。

我们是否在收到错误时通过抛出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);
}

这只是一个示例代码,验证错误或服务器错误都无关紧要,我只是想知道最佳实践,每种方法的优缺点。

共有3个答案

太叔英锐
2023-03-14

看起来验证比错误/异常更麻烦,所以我将对这两个问题都说一下。

null

null

public class Customer
{ 
    [Require]
    public string Name { get; set; }
}

然后您可以使用一个 ,它自动将验证消息发送回客户端

public class ValidationActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var modelState = actionContext.ModelState;

        if (!modelState.IsValid) {
            actionContext.Response = actionContext.Request
                 .CreateErrorResponse(HttpStatusCode.BadRequest, modelState);
        }
    }
} 

有关此文件的详细信息,请访问http://ben.onfabrik.com/posts/automatic-modelstate-validation-in-aspnet-mvc

错误处理

最好向客户机返回一条表示发生的异常的消息(带有相关的状态代码)。

如果要指定消息,就必须立即使用 。但是,这将代码绑定到 对象,而您不应该需要这样做。

我通常创建我自己类型的“安全”异常,我希望客户机知道如何处理并用一个通用的500错误包装所有其他异常。

使用操作筛选器处理异常如下所示:

public class ApiExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        var exception = context.Exception as ApiException;
        if (exception != null) {
            context.Response = context.Request.CreateErrorResponse(exception.StatusCode, exception.Message);
        }
    }
}

然后您可以在全球范围内注册它。

GlobalConfiguration.Configuration.Filters.Add(new ApiExceptionFilterAttribute());

这是我的自定义异常类型。

using System;
using System.Net;

namespace WebApi
{
    public class ApiException : Exception
    {
        private readonly HttpStatusCode statusCode;

        public ApiException (HttpStatusCode statusCode, string message, Exception ex)
            : base(message, ex)
        {
            this.statusCode = statusCode;
        }

        public ApiException (HttpStatusCode statusCode, string message)
            : base(message)
        {
            this.statusCode = statusCode;
        }

        public ApiException (HttpStatusCode statusCode)
        {
            this.statusCode = statusCode;
        }

        public HttpStatusCode StatusCode
        {
            get { return this.statusCode; }
        }
    }
}

我的API可以抛出的示例异常。

public class NotAuthenticatedException : ApiException
{
    public NotAuthenticatedException()
        : base(HttpStatusCode.Forbidden)
    {
    }
}
贲培
2023-03-14

ASP.NET Web API2确实简化了它。例如,以下代码:

public HttpResponseMessage GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        var message = string.Format("Product with id = {0} not found", id);
        HttpError err = new HttpError(message);
        return Request.CreateResponse(HttpStatusCode.NotFound, err);
    }
    else
    {
        return Request.CreateResponse(HttpStatusCode.OK, item);
    }
}

找不到项时,将以下内容返回到浏览器:

HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
Date: Thu, 09 Aug 2012 23:27:18 GMT
Content-Length: 51

{
  "Message": "Product with id = 12 not found"
}

建议:除非出现灾难性错误(例如,WCF错误例外),否则不要抛出HTTP错误500。选择一个适当的HTTP状态代码来表示数据的状态。(请参阅下面的apigee链接。)

链接:

    中的异常处理 .net>
澹台岳
2023-03-14

对我来说,我通常会发送回 ,并根据抛出的异常设置相应的状态代码,如果异常是致命的,则将决定是否立即发送回

在一天结束时,它是一个API发送回响应而不是视图,所以我认为向消费者发送带有异常和状态代码的消息是很好的。我目前还不需要累积错误并将其发回,因为大多数异常通常是由于不正确的参数或调用等造成的。

我的应用程序中的一个例子是,有时客户机会请求数据,但没有任何可用数据,因此我抛出一个自定义的 ,让它冒泡到Web API应用程序中,然后在我的自定义过滤器中捕获它,它发送回一条相关消息以及正确的状态代码。

我不是100%确定什么是最好的实践,但这对我来说是有效的,所以这就是我正在做的。

更新:

自从我回答了这个问题之后,有几篇博客文章是关于这个主题的:

https://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling

(此版本在夜间构建中有一些新功能)https://docs.microsoft.com/archive/blogs/youssefm/error-handling-in-asp-net-webapi

更新2

null

null

对于发生在较高层的错误,即服务器错误,我们让异常冒泡到Web API应用程序,这里我们有一个全局异常过滤器,它查看异常,用ELMAH记录它,并尝试理解它,在 中再次设置正确的HTTP状态代码和相关的友好错误消息作为主体。对于我们不期望的异常,客户机将收到默认的500内部服务器错误,但由于安全原因,一个一般消息。

更新3

null

public class NotFoundWithMessageResult : IHttpActionResult
{
    private string message;

    public NotFoundWithMessageResult(string message)
    {
        this.message = message;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = new HttpResponseMessage(HttpStatusCode.NotFound);
        response.Content = new StringContent(message);
        return Task.FromResult(response);
    }
}
 类似资料:
  • 这是我的操作方法 返回此错误的最佳实践是什么?以一种用户友好的方式,并且在发生错误时我可以识别该错误。

  • 问题内容: 今天,我在登录表单后面添加了额外的安全检查,以减缓暴力攻击。我有多个登录表单,并提供了一个易于调用的函数,该函数可以进行所有检查,然后返回结果。 问题是结果不是单个值,结果包括: 为此,我创建了一个新类。这一切都很好。 但是我经常有方便的实用程序函数,这些函数会返回多个值,并开始发现每次为结果创建一个新类都有些烦人。 有没有更好的方法来返回多个值?还是我只是懒惰?:) 问题答案: 不,

  • 如果发生错误,我应该以什么格式将响应返回给API用户?只需将响应作为状态代码和错误消息返回即可: (状态401已返回) 或者最好以这种格式返回:

  • 问题内容: 在 一般的 ,假设你有一个像下面的方法。 在发现错误的该特定方法中,在这种情况下,我不想返回空列表,因为这可能是对此特定方法调用的真正答案,我想返回一些内容以指示参数不正确。因此,在这种情况下,如果出错,我将返回False,否则返回一个列表(是否为空)。 我的问题是,在这样的领域中,不仅针对列表,什么是最佳实践?返回我想要的任何内容,并确保将其记录下来以供用户阅读?:-)你们大多数人都

  • 我想回复ResponseEntity的回复。我对在ResponseEntity中提到返回类型的最佳实践有点困惑。 这是我的控制器: 我的主要责任: 这里我的返回类型是GenericResponse、AdminAccount。在ResponseEntity中提及所有退货类型是否是一种良好的做法? 哪个是最好的方法

  • 现在我打算创建一个更好的错误处理的“应用程序”框架,我试图寻找最佳实践,但没有找到任何 泽西文档:https://Jersey.java.net/nonav/documentation/1.9/user-guide.html#D4E443 Internet上的几个搜索:http://www.codingpedia.org/ama/error-handing-in-rest-api-with-jer