我对我们向客户返回错误的方式有顾虑。

当我们得到一个错误时,我们是否通过抛出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);
}

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


当前回答

如果您正在使用ASP。NET Web API 2,最简单的方法是使用ApiController Short-Method。这将导致一个BadRequestResult。

return BadRequest("message");

其他回答

如果您正在使用ASP。NET Web API 2,最简单的方法是使用ApiController Short-Method。这将导致一个BadRequestResult。

return BadRequest("message");

试试这个

[HttpPost]
public async Task<ActionResult<User>> PostUser(int UserTypeId, User user)
{
  if (somethingFails)
  {
    // Return the error message like this.
    return new BadRequestObjectResult(new
    {
      message = "Something is not working here"
    });
  }

  return ok();
}

看起来你在验证方面遇到的麻烦比错误/异常更多,所以我将对两者都说一点。

验证

控制器动作通常应该采用Input Models,其中验证直接在模型上声明。

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

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

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

错误处理

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

开箱即用,你必须使用Request。如果你想指定一个消息,CreateErrorResponse(HttpStatusCode, message)。但是,这将代码绑定到Request对象,而您不应该这样做。

我通常创建自己的“安全”异常类型,我希望客户端知道如何处理和包装所有其他通用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)
    {
    }
}

对于Web API 2,我的方法始终返回IHttpActionResult,所以我使用…

public IHttpActionResult Save(MyEntity entity)
{
    ....
    if (...errors....)
        return ResponseMessage(
            Request.CreateResponse(
                HttpStatusCode.BadRequest, 
                validationErrors));

    // otherwise success
    return Ok(returnData);
}

你可以抛出一个HttpResponseException

HttpResponseMessage response = 
    this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "your message");
throw new HttpResponseException(response);