.net core数据模型验证,且返回数据保持接口格式的一致性

前言

今天在.net Core中使用数据模型验证时,数据验证不通过时,返回的数据结构格式与前端定义的不同,为了解决返回数据保持接口格式的一致性,故写此篇文章。.

传统验证

[HttpPost("TestInfo")]
        public async Task<AndroidApiResult<string>> TestInfo(TestInfo test)
        {
            await Task.Delay(0);
            if (string.IsNullOrEmpty(test.Name))
            {
                return GenAndroidActionResult("名字不能为空");
            }
            return GenAndroidActionResult("测试数据模型成功");
        }

如果Model类的校验的字段较多,且多个地方都使用到该Model,很多接口相同的地方都要写,使得代码显得比较臃肿,所以模型验证就有了用武之地。

模型验证

public class TestInfo
    { 
        [Required(ErrorMessage ="名字不能为空")]
        public string Name { get; set; }
        [System.ComponentModel.DataAnnotations.Phone(ErrorMessage ="电话格式不正确")]
        public string Phone { get; set; }
        
        public string Gender { get; set; }
    }

在模型参数上打上注解即可。

内置特性全部在System.ComponentModel.DataAnnotations命名空间下,主要有

  • [CreditCard]:验证属性是否具有信用卡格式。

  • [Compare]:验证模型中的两个属性是否匹配。

  • [EmailAddress]:验证属性是否具有电子邮件格式。

  • [Phone]:验证属性是否具有电话号码格式。

  • [Range]:验证属性值是否在指定的范围内。

  • [RegularExpression]:验证属性值是否与指定的正则表达式匹配。

  • [Required]:验证字段是否不为 null。

  • [StringLength]:验证字符串属性值是否不超过指定长度限制。

  • [Url]:验证属性是否具有 URL 格式。

  • [Remote]:通过在服务器上调用操作方法来验证客户端上的输入。

验证上面代码:

.net core数据模型验证,且返回数据保持接口格式的一致性

当Name字段和Phone字段格式不正确时,返回的model和我们实际定义的model不一样,增加了前端的工作量,故让我使用数据模型时,返回数据保持接口格式的一致性。

故了解到了ConfigureApiBehaviorOptions统一模型验证

模型验证一共有两种方式:

一:使用自定义动作过滤器

创建ModelValidateActionFilterAttribute类 ,继承ActionFilterAttribute

public  class ModelValidateActionFilterAttribute:ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            if (!context.ModelState.IsValid)
            {
                //获取验证失败的模型字段
                var errors = context.ModelState
                    .Where(e => e.Value.Errors.Count > 0)
                    .Select(e => e.Value.Errors.First().ErrorMessage)
                    .ToList();

                var str = string.Join("|", errors);

                //设置返回内容
                var result = new
                {
                    Code = 0,
                    Msg = "未通过数据验证。",
                    FullMsg = str
                };

                context.Result = new BadRequestObjectResult(result);
            }

        }
    }

然后,Startup.ConfigureServices将过滤器添加到控制器中并关闭默认模型验证

services.Configure<ApiBehaviorOptions>(opt => opt.SuppressModelStateInvalidFilter = true);
            services.AddControllers(opt =>
            {
                //添加过滤器
                opt.Filters.Add(typeof(ModelValidateActionFilterAttribute));
            });

再次测试,数据格式与我们想要的一致了。

.net core数据模型验证,且返回数据保持接口格式的一致性二:在AddControllers()后添加ConfigureApiBehaviorOptions实现自定义BadRequest响应

 services.AddControllers()
                .ConfigureApiBehaviorOptions(options =>
                {
                    //options.SuppressConsumesConstraintForFormFileParameters = true; //SuppressUseValidationProblemDetailsForInvalidModelStateResponses;
                    //自定义 BadRequest 响应
                    options.InvalidModelStateResponseFactory = context =>
                    {
                        var problemDetails = new ValidationProblemDetails(context.ModelState);
                        var resultDto = new ApiResultSmallHump { code = ApiResultCode.Failed, data = null, message = "错误" };
                        return new BadRequestObjectResult(resultDto)
                        {
                            ContentTypes = { "application/json" }

                        };

                    };
                });