【问题标题】:Override the response body of RequiredAttribute in DataAnnotation in .NET Core / .NET 5在 .NET Core / .NET 5 的 DataAnnotation 中覆盖 RequiredAttribute 的响应主体
【发布时间】:2021-10-08 12:27:18
【问题描述】:

将所需属性添加到 API 请求模型后,然后当请求正文无效时,我得到的响应为

{
   "type":"<type_URL>",
   "title":"One or more validation errors occurred.",
   "status":400,
   "traceId":"<trace_id_guid>",
   "errors":{
      "Id":[
         "Value is required"
      ]
   }
}

我想把这个身体改成类似,

{
    "status":400,
    "errors":[
       "Value is required"
    ]
 }

是否可以重写一些函数来得到这个结果?

【问题讨论】:

标签: c# asp.net-core-webapi asp.net-core-3.1 .net-5


【解决方案1】:

您可以创建一个包含返回字段的自定义 ValidationError 模型,然后尝试使用操作过滤器来处理验证失败错误响应。检查以下示例代码:

  1. 创建包含返回字段的自定义 ValidationError 模型:

     public class ValidationResultModel
     {
         public string status { get; }
    
         public List<ValidationError> Errors { get; }
    
         public ValidationResultModel(ModelStateDictionary modelState)
         {
             status = "400";
             Errors = modelState.Keys
                     .SelectMany(key => modelState[key].Errors.Select(x => new ValidationError(key, x.ErrorMessage)))
                     .ToList();
         }
     }
     public class ValidationError
     { 
         public string Field { get; }
    
         public string Message { get; }
    
         public ValidationError(string field, string message)
         {
             Field = field != string.Empty ? field : null;
             Message = message;
         }
     }
    
  2. 创建自定义 IActionResult。默认情况下,当显示验证错误时,会返回 BadRequestObjectResult,HTTP 状态码为 400。这里我们可以更改 Http 状态码。

     public class ValidationFailedResult : ObjectResult
     {
         public ValidationFailedResult(ModelStateDictionary modelState)
             : base(new ValidationResultModel(modelState))
         {
             StatusCode = StatusCodes.Status400BadRequest;
         }
     }
    
  3. 创建自定义动作过滤器属性:

     public class ValidateModelAttribute : ActionFilterAttribute
     {
         public override void OnActionExecuting(ActionExecutingContext context)
         {
             if (!context.ModelState.IsValid)
             {
                 context.Result = new ValidationFailedResult(context.ModelState);
             }
         }
     }
    
  4. 在 Startup.ConfigureServices 中将默认响应类型更改为 SerializableError:

         services.AddControllers().ConfigureApiBehaviorOptions(options =>
         {
             options.InvalidModelStateResponseFactory = context =>
             {
                 var result = new ValidationFailedResult(context.ModelState);
    
                 // TODO: add `using System.Net.Mime;` to resolve MediaTypeNames
                 result.ContentTypes.Add(MediaTypeNames.Application.Json);
                 result.ContentTypes.Add(MediaTypeNames.Application.Xml);
    
                 return result;
             };
         });
    
  5. 在操作方法或控制器中添加自定义操作过滤器 (ValidateModel)。

     [Route("api/[controller]")]
     [ApiController]
     [ValidateModel]
     public class ToDoController : ControllerBase
     {
    
  6. 使用 DataAnnotations 创建模型:

     public class User
     {
         public int UserId { get; set; }
         [Required]
         public string UserName { get; set; } 
     }
    
  7. API 控制器:

     [Route("api/[controller]")]
     [ApiController]
     [ValidateModel]
     public class ToDoController : ControllerBase
     {
         [HttpPost("AddUser")]
         public async Task<ActionResult> AddUser([FromBody] User model)
         {
             if (ModelState.IsValid)
             {
                 var result = "userID: " + model.UserId + " UserName: " + model.UserName;
                 return Ok(result);
             }
             return BadRequest(ModelState);
         }
    

运行应用程序后,结果如下:

【讨论】:

  • 当我发送一个无效的 json 时得到的响应是什么。这可以让我覆盖它吗?
猜你喜欢
  • 2022-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-13
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多