標籤:
ABP應用程式層——參數有效性驗證
基於DDD的現代ASP.NET開發架構--ABP系列之17、ABP應用程式層——參數有效性驗證
ABP是“ASP.NET Boilerplate Project (ASP.NET樣板項目)”的簡稱。
ABP的官方網站:http://www.aspnetboilerplate.com
ABP在Github上的開源項目:https://github.com/aspnetboilerplate
應用程式的輸入資料首先應該被檢驗是否有效。輸入的資料能被使用者或其他應用程式提交。在Web應用中,通常進行2次資料有效性檢驗:包括用戶端檢驗和服務端檢驗。用戶端的檢驗主要是使使用者有一個好的使用者體驗。 首先最好是在用戶端檢驗其表單輸入的有效性並且展示給用戶端的那些欄位輸入是無效的。但是,伺服器端的校正是更關鍵和不可缺失的(不要只做用戶端檢驗而不做伺服器端檢驗)。
伺服器端的檢驗通常是被應用服務(層)執行,應用服務(層)中的方法首先檢驗資料的有效性,然後才使用這些通過驗證的資料。ABP的基礎設施提供了自動檢驗輸入資料有效性的方法。
應用服務(層)方法得到一個資料轉送對象(DTO)作為輸入。ABP有一個IValidate的介面,DTO通過實現這個介面能夠檢驗資料的有效性。由於IInputDto擴充自IValidate,所以你可以直接實現IInputDto 介面來對資料轉送對象(DTO)檢驗其有效性。
使用資料註解
ABP提供資料註解的特性。假設我們正在開發一個建立任務的應用服務並且得到了一個輸入,請看下面樣本:
public class CreateTaskInput : IInputDto{ public int? AssignedPersonId { get; set; } [Required] public string Description { get; set; }}
在這裡,Description 屬性被標記為 Required。AssignedPersonId 是可選的。在 System.ComponentModel.DataAnnotations 命名空間中,還有很多這樣的特性 ( 例如: MaxLength, MinLength, RegularExpression 等等 )。
在System.ComponentModel.DataAnnotations 命名空間中,請看Task application service 的實現
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應用的一個普通類。
自訂檢驗
如果資料註解的方式不能滿足你的需求,你可以實現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"; } }}
希望更多國內的架構師能關注到ABP這個項目,也許這其中有能協助到您的地方,也許有您的參與,這個項目可以發展得更好。
歡迎加ABP架構設計交流QQ群:134710707
點這裡進入ABP系列文章總目錄
ABP應用程式層——參數有效性驗證