本系列目录: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继承IValidatableObjectICustomValidate,并实现验证逻辑,例如:

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" }));
}
}
}

这两个接口用法差不多,差异在于:

  1. IValidatableObject接口是定义在System.ComponentModel.DataAnnotations命名空间中;
  2. 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入参验证使用方法及经验分享的更多相关文章

  1. 2017.10.26 JavaWeb----第五章 JavaBean技术

    JavaWeb----第五章 JavaBean技术 (1)JavaBean技术 JavaBean技术是javaweb程序的重要组成部分,是一个可重复使用的软件组件,是用Java语言编写的.遵循一定的标 ...

  2. 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 ...

  3. 2017.10.28 针对Java Web应用中错误异常处理方法的运用

    针对Java Web应用中错误异常处理方法的运用 在javaweb中其异常都需要对Checked Exception之下的Exception进行继承,并且有选择地对发生的错误和异常进行处理.Java同 ...

  4. paper 10:支持向量机系列七:Kernel II —— 核方法的一些理论补充,关于 Reproducing Kernel Hilbert Space 和 Representer Theorem 的简介。

    在之前我们介绍了如何用 Kernel 方法来将线性 SVM 进行推广以使其能够处理非线性的情况,那里用到的方法就是通过一个非线性映射 ϕ(⋅) 将原始数据进行映射,使得原来的非线性问题在映射之后的空间 ...

  5. 2017/10 冲刺NOIP集训记录:暁の水平线に胜利を刻むのです!

    前几次集训都没有记录每天的点滴……感觉缺失了很多反思的机会. 这次就从今天开始吧!不能懈怠,稳步前进! 2017/10/1 今天上午进行了集训的第一次考试…… 但是这次考试似乎是近几次我考得最渣的一次 ...

  6. 欢迎来怼——第14次Scrum会议(10/26)

    一.小组信息 队名:欢迎来怼小组成员队长:田继平成员:李圆圆,葛美义,王伟东,姜珊,邵朔,冉华 小组照片 二.开会信息 时间:2017/10/26  17:00~17:13(总计13min).地点:计 ...

  7. ABP(现代ASP.NET样板开发框架)系列之10、ABP领域层——实体

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之10.ABP领域层——实体 ABP是“ASP.NET Boilerplate Project (ASP.NET样板 ...

  8. 九月 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 ...

  9. 浅入 ABP 系列(4):事件总线

    浅入 ABP 系列(4):事件总线 版权护体作者:痴者工良,微信公众号转载文章需要 <NCC开源社区>同意. 目录 浅入 ABP 系列(4):事件总线 事件总线 关于事件总线 为什么需要这 ...

随机推荐

  1. 使用 IntelliJ IDEA 开发 Android 应用程序时配置 Allatori 进行代码混淆

    IntelliJ IDEA 提供了非常强大的 Android 开发支持,就连 Google 官方推荐的 Android Studio 其实也是 IntelliJ IDEA 的一个 Android 开发 ...

  2. hdu 5400(思路题)

    Arithmetic Sequence Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

  3. php解析json字符串变量总是空白null

    通过接口获取的json字符串使用json_decode始终无法正确解析,返回空白. 直接把结果字符串复制出来手动创建一个变量却正常,在前端js也能解析,搞了半天不得其解,最后发现是接口输出的结果包含有 ...

  4. MySQL通用编程

    第一阶段:基础入门 第一章:关系模型 第二章:基本查询 第三章:复杂查询 第四章:权限控制 第五章:查询优化 第二阶段:模型设计 第六章:设计选择 第七章:函数依赖 第八章:分解算法 第九章:设计过程 ...

  5. codevs——1008 选数

    1008 选数 2002年NOIP全国联赛普及组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 已知 n ...

  6. Spring异步任务处理,@Async的配置和使用

    本文转自http://blog.csdn.net/clementad/article/details/47403185 感谢作者 这个注解用于标注某个方法或某个类里面的所有方法都是需要异步处理的.被注 ...

  7. 在Dev GridControl中添加颜色可变的ProgressBar z

    在使用DevExpress,GridControl自带的ProgressBarControl的时候 由于无法通过BackColor/ForeColor来改变进度条的颜色所以很多特效是实现不了的.如下面 ...

  8. 计算广告、推荐系统论文以及DSP综述

    http://www.huxmarket.com/detail/2966 DSP场景假定前提: 以CTR预估为例,向广告主以CPC(OCPC)方式收费,向ADX以CPM方式付费.投放计划受预算限制,在 ...

  9. linux下脚本监控网络流量

    linux下脚本监控网络流量 学习了:https://blog.csdn.net/chenghuikai/article/details/48437479 学习了:http://www.jb51.ne ...

  10. tomcat7设置usernamepassword

    因为tomcat是绿色版.今天想在网页上管理项目,却发现没实username和password.打开tomcat-users.xml文件全都是凝视.如图: 将例如以下代码拷贝到tomcat-users ...