首页 > 解决方案 > 对 ASP.NET Core 中缺少所需属性的响应

问题描述

给定以下控制器:

using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;

namespace WebApplication1.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        // POST api/values
        [HttpPost]
        public ActionResult<string> Post([FromBody] Model req)
        {
            return $"Your name is {req.Name}";
        }
    }

    public class Model
    {
        [Required] public string Name { get; set; }
    }
}

如果我发布一个空的 body {},响应是:

{
    "errors": {
        "Name": [
            "The Name field is required."
        ]
    },
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "80000002-0002-ff00-b63f-84710c7967bb"
}

我想更改此响应,以便将错误消息自动传递给用户变得更容易。所以我希望它看起来更像这样:

{
    "error": 999,
    "message": "Field 'name' is required."
}

我试图RequiredAttribute像这样扩展 -class:

public class MyRequiredAttribute : RequiredAttribute
{
    public MyRequiredAttribute()
    {
        ErrorMessage = "{0} is required";
    }
}

遗憾的是,它只会更改集合中返回的字符串,就像这样

{
    "errors": {
        "Name": [
            "Name is required"
        ]
    },
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "80000006-0000-ff00-b63f-84710c7967bb"
}

标签: c#validationasp.net-core

解决方案


在使用应用了 ApiController 属性的控制器时,ASP.NET Core 通过返回 400 Bad Request 并以 ModelState 作为响应正文来自动处理模型验证错误。它与自动 HTTP 400 响应有关。您可以自定义 BadRequest 响应,如下所示:

  services.AddMvc()
                .ConfigureApiBehaviorOptions(options =>
                {
                    options.InvalidModelStateResponseFactory = actionContext =>
                    {
                        var modelState = actionContext.ModelState;
                        return new BadRequestObjectResult(FormatOutput(modelState));
                    };
                })
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

根据您的心血来潮定制FormatOutput方法。

public List<Base> FormatOutput(ModelStateDictionary input)
    {
        List<Base> baseResult = new List<Base>();
        foreach (var modelState in input.Values)
        {
            foreach (ModelError error in modelState.Errors)
            {
                Base basedata = new Base();
                basedata.Error = StatusCodes.Status400BadRequest;
                basedata.Message =error.ErrorMessage; 
                baseResult.Add(basedata);
            }
        }
        return baseResult;
    }

public class Base
{
    public int Error { get; set; }
    public string Message { get; set; }
}

推荐阅读