ABP應用層——參數有效性驗證

應用程序的輸入數據首先應該被檢驗是否有效。輸入的數據能被用戶或其餘應用程序提交。在Web應用中,一般進行2次數據有效性檢驗:包括客戶端檢驗和服務端檢驗。客戶端的檢驗主要是使用戶有一個好的用戶體驗。 首先最好是在客戶端檢驗其表單輸入的有效性而且展現給客戶端的那些字段輸入是無效的。可是,服務器端的校驗是更關鍵和不可缺失的(不要只作客戶端檢驗而不作服務器端檢驗)。服務器

服務器端的檢驗一般是被應用服務(層)執行,應用服務(層)中的方法首先檢驗數據的有效性,而後才使用這些經過驗證的數據。ABP的基礎設施提供了自動檢驗輸入數據有效性的方法。app

應用服務(層)方法獲得一個數據傳輸對象(DTO)做爲輸入。ABP有一個IValidate的接口,DTO經過實現這個接口可以檢驗數據的有效性。因爲IInputDto擴展自IValidate,因此你能夠直接實現IInputDto 接口來對數據傳輸對象(DTO)檢驗其有效性。ui

使用數據註解

ABP提供數據註解的特性。假設咱們正在開發一個建立任務的應用服務而且獲得了一個輸入,請看下面示例:spa

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

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

在這裏,Description 屬性被標記爲 Required。AssignedPersonId 是可選的。在 System.ComponentModel.DataAnnotations 命名空間中,還有不少這樣的特性 ( 例如: MaxLength, MinLength, RegularExpression 等等 )。code

在System.ComponentModel.DataAnnotations 命名空間中,請看Task application service 的實現orm

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

正如你所看到的,這裏沒有寫任何的數據驗證性代碼(指對Description屬性的驗證)由於ABP會自動去檢驗數據的有效性。ABP也會檢驗輸入數據是否爲null。若是爲空則會拋出AbpValidationException 異常。因此你不須要寫檢驗數據是否爲null值的代碼。若是有任何屬性的輸入數據是無效的它也會拋出相同的異常。對象

這個機制近似於 ASP.NET MVC 的驗證功能,注意:這裏的應用服務類不是繼承自Controller,它是用在Web應用的一個普通類。blog

自定義檢驗

若是數據註解的方式不能知足你的需求,你能夠實現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 的屬性。若是該屬性是真,AssignedPersonId 屬性會被檢驗是否有效,不然該屬性能夠爲空。若是有驗證錯誤,咱們必須添加把這些驗證結果添加到結果集合中。(就是將ValidationResult 添加到results)繼承

設置缺省值

在檢驗數據有效性後,咱們須要執行一個額外的操做來整理DTO參數。ABP定義了一個IShouldNormalize接口,這個接口聲明瞭一個 Normalize的方法。若是你實現了這個接口,在檢驗數據有效性後,Normalize方法會被調用。假設咱們的DTO須要一個排序方向的數據。若是這個Sorting屬性沒有被提供數據,那麼在Normalize咱們能夠給Sorting設置一個缺省值。

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

    public void Normalize()
    {
        if (string.IsNullOrWhiteSpace(Sorting))
        {
            Sorting = "Name ASC";
        }
    }
}
相關文章
相關標籤/搜索