一个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. 协同合约HACKATHON 0X03;

    协同合约HACKATHON 0X03; 使用Fetch.AI技术开发一个共享行程协同合约.超过100,000个FET代币奖励. 介 绍 拼车是对你的钱包和环境都非常有益的,因此UberPool™等共享 ...

  2. mysql常用时间函数与类型转换

    一.用到的函数有: 1.时间格式化函数  DATE_FORMAT(date,format) 2.时间加减函数DATE_ADD(date,INTERVAL expr unit)DATE_SUB(date ...

  3. 安装FeedReader添加RSS订阅

    #0x1 FeedReader FeedReader是一款功能齐全,界面优美的GTK+ 3RSS阅读器客户端,用于在线RSS服务. FeedReader目前支持Feedbin,Feedly,Fresh ...

  4. Python爬虫:手把手教你写迷你爬虫架构

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:我爱学Python 语言&环境 语言:继续用Python开路 ...

  5. tinymce 设置和获取编辑器的内容

    $('目标元素').html(插入的内容) //设置tinymce编辑器的内容tinymce.get('目标元素').getContent() //获取tinymce编辑器的内容

  6. Python 之 Restful API设计规范

    理解RESTful架构 Restful API设计指南 理解RESTful架构 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式 ...

  7. MnasNet:经典轻量级神经网络搜索方法 | CVPR 2019

    论文提出了移动端的神经网络架构搜索方法,该方法主要有两个思路,首先使用多目标优化方法将模型在实际设备上的耗时融入搜索中,然后使用分解的层次搜索空间,来让网络保持层多样性的同时,搜索空间依然很简洁,能够 ...

  8. 在Access中执行SQL

    1.基本介绍 Microsoft Access在很多地方得到广泛使用,例如小型企业,大公司的部门.喜爱编程的开发人员亦利用它来制作处理数据的桌面系统.它也常被用来开发简单的WEB应用程序. 2.Ace ...

  9. PyQt5模型视图委托

    Model-View-Delegate 模型视图委托(MVD)是PyQt中特有的设计模式,类似MVC设计模式,将MVC设计模式中的Controller当做MVD中的Delegate,两者的概念基本相同 ...

  10. 高效C++:让自己习惯C++

    视C++为一个联邦语言 面向过程,面向对象,泛型编程,元编程,C++同时支持,强大而迷惑 C++语言可以分为如下4个部分: C,C语言相同 C with Class,包括封装.继承.多态... Tem ...