分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 技术分享

从零写一个Asp.net core手脚架(模型验证)

发布时间:2023-09-06 02:33责任编辑:苏小强关键词:暂无标签

一个asp.net core项目,一定包含了各种的实体,在RESTful api里面,有很多的参数传递,不建立实体则大量的参数需要自定验证正确性,并且Action上面会写的密密麻麻的参数

在asp.net 2.0的时候,就推出了ModelState,顾名思义,这个是模型状态,用于验证实体对象的

如何模型验证

用法是在需要验证的地方打上继承了ValidationAttribute的特性,比如常见的RequiredAttribute,这个是验证对象是否存在

 ???/// <summary> ???/// Admin Request Model ???/// </summary> ???public class AdminRequestModel ???{ ???????/// <summary> ???????/// User ???????/// </summary> ???????[Required] ???????public string User { get; set; } ???????/// <summary> ???????/// Account ???????/// </summary> ???????[Required] ???????public string Account { get; set; } ???}

这是一个实体

我们要验证的Model里是“User”属性和“Account”属性不能为空

写在Action上面

 ???????/// <summary> ???????/// Test Admin ???????/// </summary> ???????/// <param name="model"></param> ???????/// <returns></returns> ???????[HttpPost("Admin")] ???????public ResponseModel Admin(AdminRequestModel model) ???????{ ???????????return new AdminResponseModel() ???????????{ ???????????????User = model.User ???????????}; ???????}

在asp.net core 2.1之前版本的web api则改为

 ???????/// <summary> ???????/// Test Admin ???????/// </summary> ???????/// <param name="model"></param> ???????/// <returns></returns> ???????[HttpPost("Admin")] ???????public ResponseModel Admin([FromForm] AdminRequestModel model) ???????{ ???????????return new AdminResponseModel() ???????????{ ???????????????User = model.User ???????????}; ???????}

进入了Action的就是通过了基础模型验证的实体对象,数据库操作之类的业务验证,就在Action里面处理

怎么启用模型验证

全局过滤器

 ???/// <summary> ???/// Gold Filter Validate Model ???/// </summary> ???public class GoldModelFilter : IActionFilter ???{ ???????/// <summary> ???????/// Action Before ???????/// </summary> ???????/// <param name="context"></param> ???????public void OnActionExecuted(ActionExecutedContext context) ???????{ ???????} ???????/// <summary> ???????/// Action After ???????/// </summary> ???????/// <param name="context"></param> ???????public void OnActionExecuting(ActionExecutingContext context) ???????{ ???????????if (!context.ModelState.IsValid) ???????????????throw new ValidateException( ???????????????????context.ModelState.Values ???????????????????????.FirstOrDefault(item => item.Errors.Count > 0 ???????????????????????) ???????????????????????.Errors.FirstOrDefault().ErrorMessage ???????????????); ???????} ???}

然后在

Startup.cs的ConfigureService内写的AddMvc改为

 ???????????services.AddMvc(options=> { ???????????????options.Filters.Add<GoldModelFilter>(); ???????????}));

我们不需要全局验证的则这样写

 ???public class ModelFilterAttribute:ActionFilterAttribute ???{ ???????/// <summary> ???????/// Action Before ???????/// </summary> ???????/// <param name="context"></param> ???????public override void OnActionExecuted(ActionExecutedContext context) ???????{ ???????????//leave out ???????} ???????/// <summary> ???????/// Action After ???????/// </summary> ???????/// <param name="context"></param> ???????public override void OnActionExecuting(ActionExecutingContext context) ???????{ ???????????//leave out ???????} ???}

是不是很像,是的,就是一样的,只是一个是特性,一个是过滤器,内部的流程也差不多

ActionFilterAttribute还有很多东西,就暂不赘述了

我们在需要模型验证的Action上面打上特性就可以了

如何扩展自定义模型验证

CustomValidationAttribute,顾名思义这个是做自定义模型验证的,支持给属性、字段、方法、参数和实体对象验证的

他有两个参数,参数1是自定义的验证类Type,参数2是方法名

自定义验证类需要是公开类,自定义方法也是公开方法

方法参数1是object类型,参数2是ValidationContext类型

参数1是验证的内容,参数2是验证的上下文

包括

DisplayName 描述名

MemberName 成员名

ObjectInstance 整个验证的实体

ObjectType 整个验证的实体类型

还一个方法GetService

这个是获取服务的,依赖注入里面的服务,可以通过这个取出来

如果我们要对之前的AdminRequestModel这个实体验证User是否等于Account,不等于,则写一条错误日志,然后验证失败

 ???/// <summary> ???/// Admin Validate ???/// </summary> ???public class AdminValidate ???{ ???????/// <summary> ???????/// Ordinary Validate ???????/// </summary> ???????/// <param name="value"></param> ???????/// <param name="validationContext"></param> ???????/// <returns></returns> ???????public static ValidationResult Ordinary(object value, ValidationContext validationContext) ???????{ ???????????if (value is AdminRequestModel model) ???????????{ ???????????????if (!model.User.Equals(model.Account)) ???????????????{ ???????????????????var logger = validationContext.GetService(typeof(ILogger<AdminValidate>)) as ILogger<AdminValidate>; ???????????????????logger.LogError("User not equals Account"); ???????????????????return new ValidationResult("User not equals Account"); ???????????????} ???????????????return ValidationResult.Success; ???????????} ???????????return new ValidationResult("Type Error"); ???????} ???}

AdminRequestModel上面加一行[CustomValidation(typeof(AdminValidate), "Ordinary")]

这种是低复用的场景下,给特定的做验证的,如果我们这种验证很多,而且很多处都有相似的验证,那么可以写一个特性,继承ValidationAttribute

这个的验证的有两种场景,单纯的内容验证,没有功能性的,比如上面这种,验证失败,悄悄写一条错误日志,甚至发一个预警邮件

那么重构两个方法FormatErrorMessage和IsValid,前者返回错误信息,后者是验证的

除了验证,还有一些功能性的

那么请重构IsValid方法

代码和AdminValidate.Ordinary雷同

扩展

如果我们的过滤特性里面也有一些功能性呢?

 ???/// <summary> ???/// Register Service Action Filter ???/// </summary> ???public class ServiceActionFilterAttribute : ActionFilterAttribute ???{ ???????private ILogger<ServiceActionFilterAttribute> Logger { get; } ???????/// <summary> ???????/// Generate ???????/// </summary> ???????/// <param name="logger"></param> ???????public ServiceActionFilterAttribute(ILogger<ServiceActionFilterAttribute> logger) ???????{ ???????????Logger = logger; ???????} ???????/// <summary> ???????/// Action Before ???????/// </summary> ???????/// <param name="context"></param> ???????public override void OnActionExecuted(ActionExecutedContext context) ???????{ ???????????//leave out ???????} ???????/// <summary> ???????/// Action After ???????/// </summary> ???????/// <param name="context"></param> ???????public override void OnActionExecuting(ActionExecutingContext context) ???????{ ???????????//leave out ???????} ???}

这样是不能打在Action上面了

这个时候,我们就要掏出ServiceFilterArribute或者TypeFilterAttribute

 ???????/// <summary> ???????/// Test Admin ???????/// </summary> ???????/// <param name="model"></param> ???????/// <returns></returns> ???????[HttpPost("AdminDIFilterAttibute")] ???????[ServiceFilter(typeof(ServiceActionFilterAttribute))] ???????public ResponseModel AdminDIFilterAttibute(AdminRequestModel model) ???????{ ???????????return new AdminResponseModel() ???????????{ ???????????????User = model.User ???????????}; ???????}

前者是Type必须注册在依赖注入容器里面的,后者是不需要的

项目地址:

https://github.com/htrlq/AspNetCoreTemplate

从零写一个Asp.net core手脚架(模型验证)

原文地址:https://www.cnblogs.com/NCoreCoder/p/10385459.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved