一个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 >
)
.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手脚架(模型验证)的更多相关文章

  1. 从零写一个Asp.net core手脚架 (异常处理)

    既然是手脚架,那么肯定得明白,手脚架是有限资源的一个整合,我们尽可能完善它,并保留可扩展性才是最终目的,尽可能减少硬编码,让业务不满足的情况下,可以自行修改 我们把解决方案取名Asp.netCoreT ...

  2. asp.net core 简化模型验证 modelState.IsValid不用每一个写

    第一种:直接在执行action之前验证模型 实现 IActionFilter public class ModelStateFilter : IActionFilter { public void O ...

  3. asp.net core自定义模型验证——前端验证

    转载请注明出处:http://www.cnblogs.com/zhiyong-ITNote/ 官方网站:https://docs.microsoft.com/zh-cn/aspnet/core/mvc ...

  4. Asp.Net Core 全局模型验证

    public class ActionFilter : IActionFilter { /// <summary> /// action 执行之前 /// </summary> ...

  5. 手把手教你从零写一个简单的 VUE--模板篇

    教程目录1.手把手教你从零写一个简单的 VUE2.手把手教你从零写一个简单的 VUE--模板篇 Hello,我又回来了,上一次的文章教会了大家如何书写一个简单 VUE,里面实现了VUE 的数据驱动视图 ...

  6. Kubernetes初探[1]:部署你的第一个ASP.NET Core应用到k8s集群

    Kubernetes简介 Kubernetes是Google基于Borg开源的容器编排调度引擎,作为CNCF(Cloud Native Computing Foundation)最重要的组件之一,它的 ...

  7. 使用Visual Studio Code创建第一个ASP.NET Core应用程序

    全文翻译自:Your First ASP.NET Core Application on a Mac Using Visual Studio Code 这篇文章将向你展示如何在Mac上写出你的第一个A ...

  8. 如何一秒钟从头构建一个 ASP.NET Core 中间件

    前言 其实地上本没有路,走的人多了,也便成了路. -- 鲁迅 就像上面鲁迅说的那样,其实在我们开发中间件的过程中,微软并没有制定一些策略或者文档来约束你如何编写一个中间件程序, 但是其中却存在者一些最 ...

  9. 手把手教你从零写一个简单的 VUE

    本系列是一个教程,下面贴下目录~1.手把手教你从零写一个简单的 VUE2.手把手教你从零写一个简单的 VUE--模板篇 今天给大家带来的是实现一个简单的类似 VUE 一样的前端框架,VUE 框架现在应 ...

随机推荐

  1. 小师妹学JVM之:JVM中的Safepoints

    目录 简介 GC的垃圾回收器 分代回收器中的问题 safepoints safepoint一般用在什么地方 总结 简介 java程序员都听说过GC,大家也都知道GC的目的是扫描堆空间,然后将那些标记为 ...

  2. Esp8266 网络结构体

    Esp8266建立网络连接相关结构体如下: 结构体头文件espconn.h /** Protocol family and type of the espconn */ enum espconn_ty ...

  3. python 面向对象专题(九):特殊方法 (二)__get__、__set__、__delete__ 描述符(二)覆盖型与非覆盖型描述符对比

    前言 根据是否定义__set__ 方法,描述符可分为两大类. 实现 __set__ 方法的描述符属于覆盖型描述符,因为虽然描述符是类属性,但是实现 __set__ 方法的话,会覆盖对实例属性的赋值操作 ...

  4. 07-Python面对对象初级

    一.简介 面对过程编程: 根据操作数据的函数或语句块来设计程序. 面对对象编程:把一些函数,数据,方法和功能结合起来,用“对象”包裹组织程序的一种方法. 类和对象是面向对象编程的两个主要方面.类创建一 ...

  5. 009.Nginx缓存及配置

    一 浏览器缓存 1.1 缓存概述 缓存对于Web至关重要,尤其对于大型高负载Web站点.Nginx缓存可作为性能优化的一个重要手段,可以极大减轻后端服务器的负载.通常对于静态资源,即较少经常更新的资源 ...

  6. C#中的类与对象

    类:说白了就是类型,是对具体事物的一种抽象总结. 对象:一个具体的事物. 类与对象的关系,类实例化就会得到一个对象,同样一个对象也应该属于某一个类.例如张三这个人,他是一个对象,同时他属于人类,在程序 ...

  7. sqlserver安装出现找不到数据库引擎错误

    sqlserver安装出现找不到数据库引擎错误 问题的解决 第一次安装SQL server,发现它较于Oracle,都有安装卸载十分麻烦的特点.刚开始安装,就让我频繁遇到这个“找不到数据库引擎”的错误 ...

  8. windows docker xshell 默认登录密码

    boot2docker用户和密码 用户 密码 进入方式 docker tcuser ssh root   command:sudo -i (docker用户下执行)

  9. 何时/如何使用 Vue3 render 函数

    什么是 DOM? 如果我们把这个 HTML 加载到浏览器中,浏览器创建这些节点,用来显示网页.所以这个HTML映射到一系列DOM节点,然后我们可以使用JavaScript进行操作.例如: let it ...

  10. APP自动化 -- MobileBy

    一.BobileBy源码 selenium中有 By appium就有MobileBy. 二.MobileBy示例 MobileBy就是继承的By,所以,语法基本是一样的.