校验数据传输对象

校验简介

  应用的输入首先应该被校验。输入可以是用户的也可以是其他应用的。在一个web应用中,校验通常实现两次:客户端和服务端。客户端校验是为了用户体验。最好现在客户端校验表单并显示给用户无效的字段。但是,服务端校验要更紧要且不可避免的。

  服务端校验一般在应用服务或控制器实现(通常,所有的服务从展示层获得数据)。应用服务方法应该先检查(校验)输入再使用。ABP提供了良好的基础设施来自动校验应用的输入:

  • 所有的应用服务方法
  • 所有的ASP.NET Core MVC控制器方法
  • 所有的ASP.NET MVC和Web API控制器方法

  参见禁用校验部分来禁用校验,如果有需要的话。  

使用数据标注

  ABP支持数据标注特性。假定我们开发了一个Task应用服务用来创建一个Task,按如下所示获取输入:

public class CreateTaskInput
{
public int? AssignedPersonId { get; set; } [Required]
public string Description { get; set; }
}

  这里,Description属性标记为Required。AssignedPersonId是可选的。在System.ComponentModel.DataAnnotations命名空间里有许多特性(如MaxLength,MinLength,RegularExpression...)。参见Task应用服务的实现:

public class TaskAppService : ITaskAppService
{
private readonly ITaskRepository _taskRepository;
private readonly IPersonRepository _personRepository; public TaskAppService(ITaskRepository taskRepository, IPersonRepository personRepository)
{
_taskRepository = taskRepository;
_personRepository = personRepository;
} public void CreateTask(CreateTaskInput input)
{
var task = new Task { Description = input.Description }; if (input.AssignedPersonId.HasValue)
{
task.AssignedPerson = _personRepository.Load(input.AssignedPersonId.Value);
} _taskRepository.Insert(task);
}
}

  如你所见,没有写验证代码,因为ABP自动校验。ABP检查input是否为null,如果为的话则抛出AbpValidationException。所以,你不用编写null-check代码(守护语句)。如果任何输入属性无效,它都会抛出AbpValidationException。

  这种机制和ASP.NET MVC的校验相似,但是注意应用服务不是继承自Controller,它是一个普通的类并且可以在web应用外使用。

自定义校验

  如果数据标注不满足你的案例,你可以按如下方式实现ICustomValidate接口:

public class CreateTaskInput : ICustomValidate
{
public int? AssignedPersonId { get; set; } public bool SendEmailToAssignedPerson { get; set; } [Required]
public string Description { get; set; } public void AddValidationErrors(CustomValidatationContext context)
{
if (SendEmailToAssignedPerson && (!AssignedPersonId.HasValue || AssignedPersonId.Value <= ))
{
context.Results.Add(new ValidationResult("AssignedPersonId must be set if SendEmailToAssignedPerson is true!"));
}
}
}

  ICustomValidate接口声明了AddValidationErrors方法。如果有校验错误,我们必须添加ValidationResult对象到context.Results列表。你可以使用context.IoCResolver来解决依赖关系,如果在校验过程中需要的话。

  除了ICustomValidate,ABP也提供了支持.NET的标准IValidatableObject接口。你也可以实现它来执行其他的自定义校验。如果你同时实现了这两个接口,它们将会都被调用。

禁用校验

  对于自动校验的类(参见介绍部分),你可以使用这些属性控制校验:

  • DisableValidation特性可以用于classes,方法或DTOs的属性来禁用校验。
  • EnableValidation特性只能用来给方法启用校验,如果它被包含的类禁用的话。

标准化

  我们可能在校验之后需要执行一些操作来安排DTO参数。ABP定义了IShouldNormalize接口,它为此有一个Normalize方法。如果你实现了这个接口,Normalize方法会在校验(仅在方法调用之前)之后调用。假定我们的DTO获取一个排序方向。如果它没被提供,我们希望设置一个默认的排序:

public class GetTasksInput : IShouldNormalize
{
public string Sorting { get; set; } public void Normalize()
{
if (string.IsNullOrWhiteSpace(Sorting))
{
Sorting = "Name ASC";
}
}
}

返回主目录

ABP官方文档翻译 4.3 校验数据传输对象的更多相关文章

  1. ABP官方文档翻译 4.2 数据传输对象

    数据传输对象 DTOs的必要性 领域层的抽象 数据隐藏 序列化和懒加载问题 DTO转换和验证 示例 DTOs和实体间的自动映射 辅助接口和类 数据传输对象用来在应用层和展示层之间传输数据. 展示层调用 ...

  2. ABP官方文档翻译 4.1 应用服务

    应用服务 IApplicationService接口 ApplicationService类 CrudService和AsyncCrudAppService类 简单的CRUD应用服务示例 自定义CRU ...

  3. ABP官方文档翻译 0.0 ABP官方文档翻译目录

    一直想学习ABP,但囿于工作比较忙,没有合适的契机,当然最重要的还是自己懒.不知不觉从毕业到参加工作七年了,没留下点儿什么,总感觉很遗憾,所以今天终于卯足劲鼓起勇气开始写博客.有些事能做的很好,但要跟 ...

  4. ABP官方文档翻译 1.2 N层架构

    N层架构 介绍 ABP架构 其他(通用) 领域层 应用层 基础设施层 网络和展现层 其他 总结 介绍 应用程序代码库的分层架构是被广泛认可的可以减少程序复杂度.提高代码复用率的技术.为了实现分层架构, ...

  5. ABP官方文档翻译 6.4 导航

    导航 创建菜单 注册导航提供者 显示菜单 每一个网络应用都会有一些菜单用来在pages/screens之间导航.ABP提供了通用的基础设施来创建并显示菜单. 创建菜单 应用可以由不同的模块组成,每一个 ...

  6. ABP官方文档翻译 2.2 ABP会话

    ABP会话 介绍 关于IAbpSession 注入会话 会话属性 覆盖当前会话值 警告! 用户标示 介绍 如果应用需要登录的话,同样也需要知道当前用户可以执行哪些操作.ABP在展现层提供了会话对象,同 ...

  7. ABP官方文档翻译 3.2 值对象

    值对象 介绍 值对象基类 最佳实践 介绍 "展现领域描述性层面且没有概念性身份的对象称之为值对象."(Eric Evans). 和实体相反,实体有身份标示(Id),值对象没有身份标 ...

  8. ABP官方文档翻译 2.7 对象到对象的映射

    对象到对象的映射 介绍 IObjectMapper接口 AutoMapper集成 安装 创建映射 自动映射属性 自定义映射 MapTo扩展方法 单元测试 预定义映射 LocalizeableStrin ...

  9. ABP官方文档翻译 10.1 ABP Nuget包

    ABP Nuget包 Packages Abp Abp.AspNetCore Abp.Web.Common Abp.Web Abp.Web.Mvc Abp.Web.Api Abp.Web.Api.OD ...

随机推荐

  1. HDU2824-The Euler function-筛选法求欧拉函数+求和

    欧拉函数: φ(n)=n*(1-1/p1)(1-1/p2)....(1-1/pk),其中p1.p2-pk为n的所有素因子.比如:φ(12)=12*(1-1/2)(1-1/3)=4.可以用类似求素数的筛 ...

  2. codeforces Gym 101063 C

    二进制转十进制 然后按位比较 传送门 http://codeforces.com/gym/101063 #include <cstdio> #include <cmath> # ...

  3. Logger之Logger.getLogger(CLass)技巧代替system.out.print

    ---恢复内容开始--- 尊重原创:http://www.cnblogs.com/zxf330301/p/5876117.html 之前一直在使用System.out.println()来调试.但是用 ...

  4. spring如何控制事务

    Spring 的事务,可以说是 Spring AOP 的一种实现. AOP面向切面编程,即在不修改源代码的情况下,对原有功能进行扩展,通过代理类来对具体类进行操作. spring是一个容器,通过spr ...

  5. fireasy 使用篇 - 简介

    一.Fireasy 简介 Fireasy是一套基于.Net Framework应用开发组件,其主旨思想为“让开发变为更简单”,其义为,使用尽可能少的组件,实现你所需的功能.Fireasy几乎覆盖了开发 ...

  6. (一)surging 微服务框架使用系列之surging 的准备工作rabbitmq安装

    (1)下载erlang: http://www.erlang.org/download/otp_win64_17.3.exe 并安装 (2)下载RabbitMQ: http://www.rabbitm ...

  7. IO代码记忆

    FileWriter fw = new FileWriter("hello.txt"); String s = "hello world"; fw.write( ...

  8. redis安装、测试&集群的搭建&踩过的坑

    1 redis的安装 1.1   安装redis 版本说明 本教程使用redis3.0版本.3.0版本主要增加了redis集群功能. 安装的前提条件: 需要安装gcc:yum install gcc- ...

  9. centos利用yum安装卸载软件常用命令

    来自:http://tech.v01.cn/Linuxchangjianwenti/changyongruanjiananzhuangyucao/2012/0119/70.html 一.使用yum安装 ...

  10. Eclipse报错An internal error occurred during: "J2EE Component Mapping Update". java.lang.NullPointerException

    Eclipse每次打开.java文件时,报错信息如下: An internal error occurred during: "J2EE Component Mapping Update&q ...