前言
今天在.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]:通过在服务器上调用操作方法来验证客户端上的输入。
验证上面代码:
当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));
});
再次测试,数据格式与我们想要的一致了。
二:在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" }
};
};
});