校验数据传输对象

简介

在应用程序中,应首先验证输入。输入可以由用户或其他应用程序发送。在Web应用程序中,验证通常执行两次:在客户端和服务器端。客户端验证主要是为了用户体验而实现的。最好先在客户端中检查表单,然后向用户显示无效字段。但是,服务器端验证是不可避免的,而且更为关键。

服务器端验证通常在应用程序服务或控制器中实现(通常,所有服务都从表示层获取数据)。应用程序服务方法应首先检查(验证)输入,然后使用它。ASP.NET Boilerplate提供了自动验证应用程序输入的基础结构:

如果需要,请参阅“禁用验证”部分以禁用验证。

使用数据注释

ASP.NET Boilerplate支持数据注释属性。假设我们正在开发一个Task应用程序服务,用于在获取输入时创建任务,如下所示:

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

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

这里,Description属性标记为RequiredAssignedPersonId是可选的。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);
    }
}

如您所见,自从ASP.NET Boilerplate自动执行验证代码以来,没有编写验证代码。ASP.NET Boilerplate还检查输入是否为null 并抛出AbpValidationException(如果是),因此您不必编写 空检查代码(guard子句)。如果任何输入属性无效,它也会抛出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(CustomValidationContext 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还支持.NET的标准IValidatableObject接口。您还可以实现它以执行其他自定义验证。如果同时实现这两个接口,则会调用它们。

禁用验证

对于自动验证的类(请参见“简介”部分),您可以使用这些属性来控制验证:

正常化

我们可能需要执行额外的操作以在验证后准备DTO参数。ASP.NET Boilerplate定义了一个 具有Normalize方法IShouldNormalize接口如果实现此接口,则在验证之后(并且在方法调用之前)调用Normalize方法。假设我们的DTO获得排序方向。如果没有提供,我们要设置默认排序:

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

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

nidie.com.cn - 用心与你沟通