[2017-10-26]Abp系列——DTO入参验证使用方法及经验分享
本系列目录:Abp介绍和经验分享-目录
声明式的入参验证逻辑
声明式入参验证主要使用了System.ComponentModel.DataAnnotations中提供的各种验证参数的Attributes,将Attribute标记到属性上,即可(这是在早期Asp.Net Mvc中就支持的写法)。
例如:
public class DemoInputDto
{
[Required]
public int? Value1 { get; set; }
[Range(0, int.MaxValue)]
public int Value2 { get; set; }
[Required]
public DateTime? Time1 { get; set; }
[RegularExpression("\\d+")]
public string RegMatchStr { get; set; }
}
以前都是配合Mvc控制器中的ModelState.IsValid即可判断参数是否验证通过。
而在ABP框架中,DTO的参数验证环节是通过IOC拦截器的机制在调用IApplicatonService接口的方法时进行验证的,如果验证不通过则会有相应的异常和错误信息输出。
稍复杂的情况,IValidatableObject,ICustomValidate
上面说的入参验证逻辑,仅限于DTO中的单个属性,如果入参验证逻辑需要针对一个DTO中的多个属性进行判断,就无法用声明式的方法去标记了。
这时,我们可以让InputDto继承IValidatableObject或ICustomValidate,并实现验证逻辑,例如:
public class DemoInputDto : IValidatableObject
{
[Required]
public int? Value1 { get; set; }
[Range(0, int.MaxValue)]
public int Value2 { get; set; }
[Required]
public DateTime? Time1 { get; set; }
[RegularExpression("\\d+")]
public string RegMatchStr { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Value1 > 5 && Value2 < 100)
{
yield return new ValidationResult("blablabla", new string[] { "Value1", "Value2" });
}
}
}
或
public class DemoInputDto : ICustomValidate
{
///...略
public void AddValidationErrors(CustomValidationContext context)
{
if (Value1 > 5 && Value2 < 100)
{
context.Results.Add(new ValidationResult("blablabla", new string[] { "Value1", "Value2" }));
}
}
}
这两个接口用法差不多,差异在于:
IValidatableObject接口是定义在System.ComponentModel.DataAnnotations命名空间中;ICustomValidate接口是ABP定义的,在Abp.Runtime.Validation命名空间中;
IValidatableObject如前所提,是Asp.Net Mvc框架原生支持的,而ABP框架同时支持这两个接口。
Tips,如果你打算直接拿应用层的DTO直接作为Mvc Action上的入参,建议用IValidatableObject。
多个DTO重用验证逻辑,OOP多态
最后这点是我自己的经验分享。
有时候,某个应用服务(例如MySettingAppService)的多个方法的InputDto含有一批类似的属性,并且有一样的入参验证逻辑。
比如一个场景,有个业务制定了等级机制,进行配置时,每个配置方法都需要针对所有等级进行配置,并且不允许针对单个等级进行配置,以防遗漏某个等级未配置。
///第一个Dto,假设叫ADto
///等级Id作为字典key,配置值是简单数字
public Dictionary<int, int> LevelGenerationCountList { get; set; }
///...
///第二个Dto,假设叫BDto
///等级Id作为字典key,配置值为value
public Dictionary<int, decimal> LevelMinimumConsuptionList { get; set; }
如果我想简单验证这两个DTO的入参是否都满足当前等级数量的要求,验证逻辑可能要重复写成这样:
public class MySettingAppService : MyAppServiceBase, IMySettingAppService
{
///...略
private async Task CheckLevelSettingsCount(ADto input)
{
if (!await _levelSettingPolicy.Satisfied(input.LevelGenerationCountList.Count))
{
throw new Abp.UI.UserFriendlyException("必须为当前所有等级提供配置!");
}
}
private async Task CheckLevelSettingsCount(BDto input)
{
if (!await _levelSettingPolicy.Satisfied(input.LevelMinimumConsuptionList.Count))
{
throw new Abp.UI.UserFriendlyException("必须为当前所有等级提供配置!");
}
}
}
DRY,这种重复代码必须消灭掉!怎么动手?OOP 多态!
自定义一个IHasLevelSettingCount,如下:
public interface IHasLevelSettingCount
{
int GetLevelSettingCount();
}
ADto和BDto都继承IHasLevelSettingCount:
public class ADto:IHasLevelSettingCount
{
///...略
public int GetLevelSettingCount()
{
return LevelGenerationCountList.Count;
}
}
public class BDto:IHasLevelSettingCount
{
///...略
public int GetLevelSettingCount()
{
return LevelMinimumConsuptionList.Count;
}
}
MySettingAppService就只需要写一个CheckLevelSettingsCount:
public class MySettingAppService : MyAppServiceBase, IMySettingAppService
{
///...略
private async Task CheckLevelSettingsCount(IHasLevelSettingCount input)
{
if (!await _levelSettingPolicy.Satisfied(input.GetLevelSettingCount()))
{
throw new Abp.UI.UserFriendlyException("必须为当前所有等级提供配置!");
}
}
}
这样,借助多态,CheckLevelSettingsCount 既可以传入ADto,又可以传入BDto,实现了验证逻辑的复用,消灭了重复代码!
[2017-10-26]Abp系列——DTO入参验证使用方法及经验分享的更多相关文章
- 2017.10.26 JavaWeb----第五章 JavaBean技术
JavaWeb----第五章 JavaBean技术 (1)JavaBean技术 JavaBean技术是javaweb程序的重要组成部分,是一个可重复使用的软件组件,是用Java语言编写的.遵循一定的标 ...
- 2017.10.26 ECN + product spec+ cypress ble module test+
1 ECN Ecn should be issued when modifying drawing,Copy children BOM of subassembly from BIL if one ...
- 2017.10.28 针对Java Web应用中错误异常处理方法的运用
针对Java Web应用中错误异常处理方法的运用 在javaweb中其异常都需要对Checked Exception之下的Exception进行继承,并且有选择地对发生的错误和异常进行处理.Java同 ...
- paper 10:支持向量机系列七:Kernel II —— 核方法的一些理论补充,关于 Reproducing Kernel Hilbert Space 和 Representer Theorem 的简介。
在之前我们介绍了如何用 Kernel 方法来将线性 SVM 进行推广以使其能够处理非线性的情况,那里用到的方法就是通过一个非线性映射 ϕ(⋅) 将原始数据进行映射,使得原来的非线性问题在映射之后的空间 ...
- 2017/10 冲刺NOIP集训记录:暁の水平线に胜利を刻むのです!
前几次集训都没有记录每天的点滴……感觉缺失了很多反思的机会. 这次就从今天开始吧!不能懈怠,稳步前进! 2017/10/1 今天上午进行了集训的第一次考试…… 但是这次考试似乎是近几次我考得最渣的一次 ...
- 欢迎来怼——第14次Scrum会议(10/26)
一.小组信息 队名:欢迎来怼小组成员队长:田继平成员:李圆圆,葛美义,王伟东,姜珊,邵朔,冉华 小组照片 二.开会信息 时间:2017/10/26 17:00~17:13(总计13min).地点:计 ...
- ABP(现代ASP.NET样板开发框架)系列之10、ABP领域层——实体
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之10.ABP领域层——实体 ABP是“ASP.NET Boilerplate Project (ASP.NET样板 ...
- 九月 26, 2017 10:18:14 上午 com.sun.jersey.server.impl.application.RootResourceUriRules <init> 严重: The ResourceConfig instance does not contain any root resource classes.
Tomcat启动错误:九月 26, 2017 10:18:14 上午 com.sun.jersey.server.impl.application.RootResourceUriRules <i ...
- 浅入 ABP 系列(4):事件总线
浅入 ABP 系列(4):事件总线 版权护体作者:痴者工良,微信公众号转载文章需要 <NCC开源社区>同意. 目录 浅入 ABP 系列(4):事件总线 事件总线 关于事件总线 为什么需要这 ...
随机推荐
- 机器学习实战读书笔记(二)k-近邻算法
knn算法: 1.优点:精度高.对异常值不敏感.无数据输入假定 2.缺点:计算复杂度高.空间复杂度高. 3.适用数据范围:数值型和标称型. 一般流程: 1.收集数据 2.准备数据 3.分析数据 4.训 ...
- 最小生成树-prim算法模板
题目描述 如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz 输入输出格式 输入格式: 第一行包含两个整数N.M,表示该图共有N个结点和M条无向边.(N<=5000,M<= ...
- 【ZJOI2016】大♂森林
题目描述 小Y家里有一个大森林,里面有 $n$ 棵树,编号从 $1$ 到 $n$ .一开始这些树都只是树苗,只有一个节点,标号为 $1$ .这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长 ...
- Chelly的串串专题
CF149E 题意:给出一个长度为n的文本串和m个模式串,求有多少个模式串可以拆成两半,使得这两半按顺序匹配(n<=2e5,m<=100) 最暴力的想法就是对于每个询问串,全部和原串做一遍 ...
- erlang debugger
http://erlang.org/doc/apps/debugger/debugger_chapter.html
- Android CrashHandler
package jason.android.utils; import android.content.Context; import android.content.pm.PackageInfo; ...
- 转: linux下的自动对时
转自: http://www.cnblogs.com/vimmer/archive/2012/05/17/2505785.html 评注:date 命令格式为: date -s 2012-08-02 ...
- margin: 0 auto; 元素水平居中布局无效
失效原因: 要给居中的元素一个宽度,否则无效. 该元素一定不能浮动或绝对定位,否则无效. 在HTML中使用<center></center>标签,需考虑好整体构架,否者全部元素 ...
- eclipse中文凝视字体太小解决方法
新安装的eclipse中文凝视字体太小.解决方法例如以下: 打开Elcipse-->点击菜单条上的"Windows"-->点击"Preferences&quo ...
- hdu4455 dp
pid=4455">http://acm.hdu.edu.cn/showproblem.php?pid=4455 Substrings Time Limit: 10000/5000 M ...