ABP框架 - 验证数据传输对象

文档目录

 

本节内容:

 

简介

一个应用的输入应当先要验证,这个输入可能来自用户或另一个应用,在一个web应用里,验证通常实现两次:在客户端和在服务端,客户端验证是为了用户体验,最好是先检查一个表单并向用户显示无效的输入,但是服务端的验证更具有决定性意义和必要性。

服务端验证通常实现在应用服务或控制器(通常,所有服务从展现层获取数据)。一个应用服务应该先检查(验证)输入然后再使用它。ABP提供了一个基础构造,自动验证一个应用的如下三个的所有输入:

如果需要禁用验证,请查看“禁用验证”小节。

 

使用数据注解

ABP支持数据注解特性,假设我们正在开发一个Task应用服务,它用来创建一个Task并需要一个输入,如下所示:

public class CreateTaskInput
{
    public int? AssignedPersonId { get; set; }

    [Required]
    public string Description { get; set; }
}

这里的Description属性被标记为Required,AssingedPersonId是可选的,在System.ComponentModel.DataAnnotations命名空间里,还有很多特性(如MaxLength、MinLenggth、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会验证如果输入为null,就抛出AbpValidationException,所以你不需要写null检查。如果输入的任何属性是无效的,它也会抛出AbpValidationException。

这种机制类似于Asp.net Mvc的验证,但请注意一个应用服务类不是从控制器继承过来,它就是一个单纯的类,甚至可以在一个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 <= 0))
        {
            context.Results.Add(new ValidationResult("AssignedPersonId must be set if SendEmailToAssignedPerson is true!"));
        }
    }
}

ICustomValidate接口定义了AddValidationErrors方法,如果有验证错误,我们必须添加ValidationResult对象到context.Results列表。在验证进度里,如果有需要,你可以用context.IocResolver来解析依赖

除了ICustomValidate,ABP也支持IValidatableObject接口。你同样也可以实现它,执行额外的自定义验证。如果你同时实现了这两个接口,这两个都会被调用。

 

禁用验证

对于自动验证类(查看“简介”小节),你可以使用这些特性来控制验证:

  • DisableValidation特性:可用在DTO的类,方法或属性上来禁用验证。
  • EnableValidation特性:在一个被禁用验证的类里,可以在方法上使用这个特性让当前方法的输入验证可用。

 

正常化

有时我们需要在验证后,执行一个额外的操作来整理DTO参数。ABP定义了IShouldNormailize接口,包含Normalize方法,如果你实现了这个接口,Normalize方法在验证后(在方法被调用前)被调用。假设我们需要从DTO里取得排序方向(升序、降序),如果未提供,我们想设置一个默认值:

public class GetTasksInput : IShouldNormalize
{
    public string Sorting { get; set; }

    public void Normalize()
    {
        if (string.IsNullOrWhiteSpace(Sorting))
        {
            Sorting = "Name ASC";
        }
    }
}

 

posted @ 2016-10-28 01:02 kid1412 阅读(...) 评论(...) 编辑 收藏