ABP理论学习之验证DTO

时间:2023-03-09 16:49:22
ABP理论学习之验证DTO

返回总目录


本篇目录

验证介绍###

首先应该验证应用的输入。用户或者其它应用都可以向该应用发送输入。在一个web应用中,验证通常要实现两次:在客户端和服务器端。客户端的验证大多数情况下是为用户体验而实现的。在客户端最好先检查一下表单,并向用户展示不合法的字段。但是服务端的验证更关键且不可避免。

服务端的验证通常实现在应用服务层。应用服务方法应首先检查(验证)输入然后再使用它。ABP提供了一个很好的基础设施来验证应用服务方法的输入。

应用服务方法接收一个DTO(数据传输对象)作为输入。ABP有一个IValidate接口,凡是实现了该接口的DTO都可以自动地进行验证。因为IInputDto继承了IValidate,因此只要为输入DTOs实现IInputDto就可以确保验证了。

使用数据注解###

ABP支持数据注解特性。假设我们要开发一个任务(Task)应用服务,该服务用于创建一个任务,它的输入参数类型如下所示:

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

这里,Description属性标记为 Required。AssignedPersonId是可选的。在 System.ComponentModel.DataAnnotations命名空间中也有很多特性(如MaxLength,MinLength,RegularExpression等等)。来看一下任务应用服务的实现:

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也会检查输入是否为null。如果为null,就会抛出 AbpValidationException。因此,你也不用写检测null的代码(保卫语句)。如果输入的属性有任何一个是非法的,那么就会抛出相同的异常。

该机制和ASP.NET MVC的验证相似,但是注意的是应用服务类不是派生自Controller,而只是一个纯粹的类并且在web应用之外工作。

自定义验证###

如果数据注解还不能满足你的情况,那么你可以实现ICustomValidate接口,如下所示:

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

ICustomValidate接口声明了要实现的AddValidationErrors方法。这里,我们有一个 SendEmailToAssignedPerson属性。如果它的值是true, 而且没有提供AssignedPersonId或值是负数,那么我们就认为这里发生了验证错误,我们必须将ValidationResult对象添加到 results集合中。

标准化###

我们可能在验证之后执行一个额外的操作来排列DTO参数。ABP定义了IShouldNormalize接口, 该接口中定义了Normalize方法来达到排列DTO参数的目的。如果你实现了该接口,那么就应该在验证之后(方法调用之前)调用Normalize方法。假如我们的DTO要有一个排序(Sorting)方向,如果没有提供的话,我们就要设置一个默认值:

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