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