一个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. 阿里云上安装启动nginx 以及在个人电脑上通过公网ip访问遇到的问题

    1.安装依赖包 //一键安装上面四个依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel 2.下载并解压安装包 ...

  2. response对象乱码--解决

    中文乱码 响应对象中文乱码,即就是response对象乱码. response对象输出中文数据乱码解决方案: 1 字节流输出响应乱码. 该情况不一定乱码.但是解决乱码的步骤是: 1) 设置浏览器打开文 ...

  3. day13 作业

    目录 1.编写文件修改功能,调用函数时,传入三个参数(修改的文件路径,要修改的内容,修改后的内容)既可完成文件的修改 2.编写tail工具 3.编写登录功能 4.编写注册功能 选做题:编写ATM程序实 ...

  4. java的干儿子锁Lock

    目录 Lock的由来 线程之间的交互 Lock方法简介 lock() lockInterruptibly() trylock() trylock(long,TimeUnit) unlock() new ...

  5. 抽象工厂模式(c++实现)

    抽象工厂模式 目录 抽象工厂模式 模式定义 模式动机 UML类图 源码实现 优点 缺点 感悟 模式定义 抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而 ...

  6. 10个Vue开发技巧助力成为更好的工程师·二

    优雅更新props 更新 prop 在业务中是很常见的需求,但在子组件中不允许直接修改 prop,因为这种做法不符合单向数据流的原则,在开发模式下还会报出警告.因此大多数人会通过 $emit 触发自定 ...

  7. Oracle修改表类型方法

    有一个表名为tb,字段段名为name,数据类型nchar(20). 1.假设字段数据为空,则不管改为什么字段类型,可以直接执行:alter table tb modify (name nvarchar ...

  8. maven项目原型(idea)

    1: internal -> appfuse-basic-jsf (创建一个基于Hibernate,Spring和JSF的Web应用程序的原型) 2: internal -> appfus ...

  9. 常用CSS颜色表

    1.16进制的CSS颜色代码 > http://www.jsjtt.com/webkaifa/HTML/65.html

  10. linux命令笔记记录(自用)

    1.解除yum锁定: sudo rm -rf /var/run/yum.pid 2.删除文件夹: rm -rf /var/log/httpd/access 3.更新pip: python -m pip ...