在 Minimal Api 中使用 DataAnnotation 模型验证

问题描述 投票:0回答:1

我正在将应用程序从 Asp.net 控制器移植到 Asp.net Minimal-Apis。当前项目正在使用基于模型的 DataAnnotations。控制器进行开箱即用的模型验证,但 MinApi 则不然。

对于如下示例,在 MinimalApi 中进行 DataAnnotation 模型验证的最佳方法是什么?

数据注释模型示例:

using System.ComponentModel.DataAnnotations;

namespace minApi.Models;

public class Account
{
  [Required]
  public int AccountId { get; set; }

  [Required, MaxLength(50)]
  public string AccountName { get; set; };

  [Required, EmailAddress]
  public string AccountEmail { get; set; };

  [Required, Phone]
  public string AccountPhone { get; set; };

  [Required, MaxLength(50)]
  public string StreetAddress { get; set; };

  [Required, MaxLength(50)]
  public string City { get; set; };

  [Required, MaxLength(2)]
  public string StateProvince { get; set; };

  [Required, MaxLength(10)]
  public string PostalCode { get; set; };

  public bool IsActive { get; set; }true;

  public override string ToString() => $"{AccountName} AccountId: {AccountId}";
}

带模型的最小 Api 示例:

accounts.MapPost("/saveAccount", (IAccountManager _accountManager, [FromBody] Account account) =>
{
    var acct = _accountManager.SaveAccount(account);

    return Results.Ok(acct);
})
c# .net data-annotations minimal-apis asp.net-minimal-apis
1个回答
0
投票

这是我在 Minimal-Apis 中验证 DataAnnotation 模型的想法。请发布任何其他建议以改进或更好的替代方案。

辅助扩展方法:

using System.ComponentModel.DataAnnotations;

namespace minApi.Helpers.Extensions;

public static class DataValidator
{
    public static (List<ValidationResult> Results, bool IsValid) DataAnnotationsValidate(this object model)
    {
       var results = new List<ValidationResult>();
       var context = new ValidationContext(model);

       var isValid = Validator.TryValidateObject(model, context, results, true);

       return (results, isValid);
   }
}

验证器助手:

using Microsoft.AspNetCore.Mvc;
using minApi.Helpers.Extensions;
using System.Reflection;

namespace minApi.Helpers;

public static class CustomRouteHandlerBuilder
{

  public static RouteHandlerBuilder Validate<T>(this RouteHandlerBuilder builder, bool firstErrorOnly = true)
  { 
     builder.AddEndpointFilter(async (invocationContext, next) =>
     {
        var argument = invocationContext.Arguments.OfType<T>().FirstOrDefault();
        var response = argument.DataAnnotationsValidate();

        if (!response.IsValid)
        {
            string errorMessage =   firstErrorOnly ? 
                                    response.Results.FirstOrDefault().ErrorMessage : 
                                    string.Join("|", response.Results.Select(x => x.ErrorMessage));

            return Results.Problem(errorMessage, statusCode: 400);
        }

        return await next(invocationContext);
     });

     return builder;
  }

}

Minimal-Api 方法中添加验证代码(最后一行):

accounts.MapPost("/saveAccount", (IAccountManager _accountManager, [FromBody] Account account) =>
{
    var acct = _accountManager.SaveAccount(account);

    return Results.Ok(acct);
})      
.Validate<Account>(); 
© www.soinside.com 2019 - 2024. All rights reserved.