1. 程式人生 > >ABP官方文件(二十五)【資料傳輸物件驗證】

ABP官方文件(二十五)【資料傳輸物件驗證】

4.3 ABP應用層 - 資料傳輸物件驗證

應用程式的輸入首先應該被驗證是否有效。輸入的資料能夠被使用者或者其它應用傳送。在web應用中,驗證通常被實現兩次:客戶端和伺服器端。客戶端驗證的實現主要用於使用者體驗。首先,最好是在客戶端檢驗表單並且向用戶展示無效的欄位。但是,相對於客戶端驗證,伺服器端驗證是更重要並且不可缺失的。

伺服器端的驗證通常是在應用層或者控制器中被實現(通常,所有的服務都是從持久層獲取資料)。應用服務中的方法首先應檢測輸入資料(有效性)然後使用這些資料。ABP為所有應用的輸入資料提供了高效的基礎設施來實現自動驗證;如:

  • 所有應用服務的方法

  • 所有ASP.NET Core MVC Controlle Actions

  • 所有ASP.NET MVC 和 Web API Controller Actions

如果需要禁用驗證,請檢視禁用驗證章節。

4.3.1 使用資料註解

ABP可以使用資料註解來檢驗資料的有效性。假設我們正在開發一個建立任務的應用服務,並且得到了一個輸入,如下所示:

public class CreateTaskInput
{
    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。如果為空則會丟擲AbpValidationException 異常。所以你不需要寫檢驗資料是否為null值的程式碼。如果有任何屬性的輸入資料是無效的它也會丟擲相同的異常。

這個機制近似於 ASP.NET MVC 的驗證功能,注意:這裡的應用服務類不是繼承自Controller,它是用在Web應用的一個普通類,即使不是一個WEB應用它也能夠正常工作。

4.3.2 自定義檢驗

如果資料註解的方式不能滿足你的需求,你可以實現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也對.NET標準的 IValidatableObject 介面提供支援。你也可以實現它來執行自定義驗證。如果你實現了這兩個介面,那麼這兩個介面的方法都會被呼叫。

4.3.3 禁用驗證

對於自動驗證類,你可以使用這些特性來控制驗證:

  • DisableValidation 特效能夠被用來對DTO的類,方法或者屬性來禁用驗證

  • EnableValidation 特性僅能夠被用來開啟都某個方法的驗證;如果對某個類禁用驗證,但是想對該類的某個方法開啟驗證

4.3.4 標準化

在驗證資料輸入後,我們需要執行一個額外的操作來組織DTO引數。ABP定義了一個 IShouldNormalize 介面,這個介面聲明瞭一個 Normalize 的方法。如果你實現了這個介面,在資料驗證後,Normalize 方法就會被呼叫。假設我們的DTO需要一個排序方向的屬性。如果這個Sorting屬性沒有值,但是我們想要設定一個預設值;如下所示:

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

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