如何使用.net Core自定义Web API中的错误响应?

Sru*_*kar 2 model asp.net-core asp.net-core-webapi

我正在使用带有Web API的.net core 2.2。我创建了一个类,即如下:

public class NotificationRequestModel
{
    [Required]
    public string DeviceId { get; set; }
    [Required]
    public string FirebaseToken { get; set; }
    [Required]
    public string OS { get; set; }

    public int StoreId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

使用上面的类,我创建了一个方法。现在,我想返回自定义对象,但返回的是它自己的对象。API方法是:

public ActionResult<bool> UpdateFirebaseToken(NotificationRequestModel model)
   {
       if (!ModelState.IsValid)
       {
          return BadRequest(FormatOutput(ModelState.Values));
       }
       var result = _notificationService.InsertOrUpdateFirebaseToken(model);
       return Ok(result);
   }
Run Code Online (Sandbox Code Playgroud)

这里的FormatOutput方法是格式化输出。

protected Base FormatOutput(object input, int code = 0, string message = "", string[] details = null)
    {
        Base baseResult = new Base();
        baseResult.Status = code;
        baseResult.Error = message;
        baseResult.TimeStamp = CommonHelper.CurrentTimeStamp;
        baseResult.Code = code;
        baseResult.Details = details;
        baseResult.Message = message; //Enum.Parse<APIResponseMessageEnum>(code.ToString(), true); // (enum of code get value from language)
        return baseResult;
    }
Run Code Online (Sandbox Code Playgroud)

但问题是它返回:

{“错误”:{“ DeviceId”:[“ DeviceId字段为必填。” ]},“ title”:“发生一个或多个验证错误。”,“ status”:400,“ traceId”:“ 80000049-0001-fc00-b63f-84710c7967bb”}

我想用我的模型自定义此错误。我需要错误消息和返回输出的详细信息,并将其传递给我的模型。我怎样才能做到这一点?我曾尝试调试我的代码,发现API方法上的断点未调用。因此,我无法处理自定义方法。有什么解决办法吗?我究竟做错了什么?任何帮助都感激不尽。谢谢。

Tao*_*hou 6

克里斯(Chris)分析后,您的问题是由自动HTTP 400响应 引起的。

对于快速解决方案,您可以通过以下方式取消此功能:

services.AddMvc()
        .ConfigureApiBehaviorOptions(options => {
            options.SuppressModelStateInvalidFilter = true;
        }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
Run Code Online (Sandbox Code Playgroud)

为了提高效率,您可以遵循Chris的建议,如下所示:

services.AddMvc()
        .ConfigureApiBehaviorOptions(options => {
            //options.SuppressModelStateInvalidFilter = true;
            options.InvalidModelStateResponseFactory = actionContext =>
            {
                var modelState = actionContext.ModelState.Values;
                return new BadRequestObjectResult(FormatOutput(modelState));
            };
        }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
Run Code Online (Sandbox Code Playgroud)

而且,您无需在操作中再定义下面的代码。

if (!ModelState.IsValid)
    {
        return BadRequest(FormatOutput(ModelState.Values));
    }
Run Code Online (Sandbox Code Playgroud)

  • 对于任何使用 services.AddControllers 的人来说,概念都是相同的: services.AddControllers().ConfigureApiBehaviorOptions(options =&gt; { options.SuppressModelStateInvalidFilter = true; }); (5认同)

Chr*_*att 5

当使用ApiController应用了属性的控制器时,ASP.NET Core会通过返回一个400 Bad Request 作为响应主体来自动处理模型验证错误ModelState。因此,您的条件测试ModelState.IsValid本质上始终是错误的(因此不会输入),因为到目前为止,仅有的请求是有效的。

您可以简单地删除该ApiController属性,但是也可以删除该属性添加的其他有益的东西。更好的选择是使用自定义响应工厂:

services.Configure<ApiBehaviorOptions>(o =>
{
    o.InvalidModelStateResponseFactory = actionContext =>
        new BadRequestObjectResult(actionContext.ModelState);
});
Run Code Online (Sandbox Code Playgroud)

基本上,这就是默认情况下发生的事情,因此您只需要相应地更改那里提供的操作,即可根据自己的想法进行自定义。