學習ASP.NET Core Razor 編程系列目錄
學習ASP.NET Core Razor 編程系列二——添加一個實體
學習ASP.NET Core Razor 編程系列三——創建數據表及創建項目基本頁面
學習ASP.NET Core Razor 編程系列四——Asp.Net Core Razor列表模板頁面
學習ASP.NET Core Razor 編程系列五——Asp.Net Core Razor新建模板頁面
學習ASP.NET Core Razor 編程系列六——數據庫初始化
學習ASP.NET Core Razor 編程系列七——修改列表頁面
學習ASP.NET Core Razor 編程系列八——並發處理
學習ASP.NET Core Razor 編程系列九——增加查詢功能
學習ASP.NET Core Razor 編程系列十——添加新字段
學習ASP.NET Core Razor 編程系列十一——把新字段更新到數據庫
本篇文章我們學習如何給 Book實體類添加校驗規則。當用戶進行創建或編輯書籍信息時,都會觸發校驗規則。
一、校驗
軟件開發中有一個主要原則被稱為 DRY(即“不要自我重復”)。 Razor 頁面鼓勵進行只需要開發一次,這個功能就能在整個應用中使用,不需要重復開發,或復制粘貼。 DRY 有助於減少應用中的代碼量。 DRY 使代碼更加不易出錯,且更易於測試和維護。
Razor 頁面和 Entity Framework框架提供的校驗是支持DRY 原則的極佳示例。 校驗規則在實體類中的某處以聲明方式指定,且在應用程序的所有位置強制執行。
二、在書籍實體類中添加校驗規則
在Visual Studio 2017的解決方案資源管理器中,打開 Models\Book.cs 文件。 DataAnnotations 提供一組內置的校驗規則特性,我們可以通過聲明的方式應用於類或屬性之上。 DataAnnotations 還包含 DataType 等格式特性,有助於格式設置但不提供驗證。
現在我們來給Book 類使用 Required、StringLength、RegularExpression 和 Range 校驗規則特性,代碼如下所示。
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace RazorMvcBooks.Models { public class Book { public int ID { get; set; } [Required] [StringLength(50, MinimumLength = 2)] public string Name { get; set; } [Display(Name = "出版日期")] [DataType(DataType.Date)] public DateTime ReleaseDate { get; set; } [Range(1,200)] [DataType(DataType.Currency)] public decimal Price { get; set; } [RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$"), Required, StringLength(30)] public string Author { get; set; } [Required] public string Publishing { get; set; } } }
校驗特性用在實體類的屬性上,並且將前端強制執行。
Required 和 MinimumLength 特性表示屬性必須具有一個值。 但是,用戶可以隨時輸入空格對可以為 null 的類型進行校驗約束。 從本質上來說,對於不能為 null 的值類型(如 decimal、int、float 和 DateTime),可以不添加 Required 特性。
RegularExpression 特性限制用戶可以輸入的字符。 在上述代碼中, Rating 只能輸入字母(禁用空格、數字和特殊字符)。
Range 特性將值限制在指定范圍內。
StringLength 特性設置字符串的最大長度,且可視情況設置最小長度。
讓 ASP.NET Core 強制自動執行校驗規則有助於提升應用程序的可靠性。 在實體類上進行自動校驗助於保護應用程序,因為添加新代碼時無需手動修改舊代碼。
三、查看面中的校驗信息
在Visual Studio 2017中按F5運行應用程序,並在瀏覽器中瀏覽到書籍列表頁面。
在書籍列表頁面,使用鼠標左鍵點擊“Create”鏈接。在新建頁面中的輸入框中輸入一些無效值。當jQuery客戶端校驗檢測到錯誤時,它會顯示一條錯誤消息。 如下圖。
備注
你可能無法在 Price 字段中輸入小數點或逗號。 若要使 jQuery 校驗支持非英英語環境中使用逗號(“,”)表替小數點,以及使用非美式英語日期格式,你必須采取應用全球化設置來改變你的應用程序。
請注意,表單在包含無效值的每個字段下自動呈現一個適當的校驗錯誤消息。錯誤包括客戶端(使用 JavaScript 和 jQuery )和服務器端(當用戶禁用JavaScript時)。
一項重要好處是,無需在“創建”或“編輯”頁面中更改代碼。 一量在在實體類上應用 DataAnnotations 后,即已啟用校驗UI。 本教程中自動創建的 Razor 頁面自動選取了校驗規則(使用Book類的屬性上的校驗特性)。 使用“編輯”頁面測試驗證后,所有應用這個Book類的頁面都應用了相同校驗規則。
存在客戶端驗證錯誤時,不會將表單數據提交到后台服務器。 你可以使用以下一種或多種方法驗證是否未發布表單數據:
1) 在 OnPostAsync 方法中放置一個斷點。 提交表單(選擇“Create”或“Save”)。 從未命中斷點。
2) 使用 Fiddler 工具。
3) 使用瀏覽器開發人員工具監視網絡流量。
四、服務器端驗證
首先我們在瀏覽器中禁用 JavaScript,即不進行客戶端校驗,然后把有錯誤的數據提交到后台服務器。
測試服務器端驗證:
1. 在瀏覽器中禁用 JavaScript。 如果你的瀏覽器中無法禁用 JavaScript,請試試其他瀏覽器。
2. 在“新建”或“編輯”頁面的 OnPostAsync 方法中設置斷點。
3. 提交帶有不符全校驗規則的表單數據。
4. 查看一下OnPostAsync方法中是否有以下代碼。
if (!ModelState.IsValid) { return Page(); }
5. 結果如下圖。
以下代碼顯示了之前在本教程中設定其基架的“Create.cshtml”的一部分。 它用於在“創建”和“編輯”頁面中顯示初始表單並在發生錯誤后重新顯示表單。
<form method="post"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="Book.Name" class="control-label"></label> <input asp-for="Book.Name" class="form-control" /> <span asp-validation-for="Book.Name" class="text-danger"></span> </div>
輸入輔助助手使用 DataAnnotations 特性並在客戶端生成 jQuery 校驗所需的 HTML 元素。 校驗輔助助手用於顯示校驗錯誤。
“創建”和“編輯”頁面中沒有校驗規則。 校驗規則和錯誤字符串僅可在BOOK 類中指定。 這些校驗規則將自動應用於編輯頁面。
當需要修改校驗邏輯時,也只能在該Book實體類中修改。 校驗將始終在整個應用程序中應用(校驗邏輯在一處定義)。 在一個地方進行校驗有助於保持代碼干凈,且更易於維護和更新。
五、使用DataType特性
現在我們在Visual Studio 2017中修改Book類。 DataAnnotations除了提供一組內置的驗證特性,System.ComponentModel.DataAnnotations 命名空間還提供格式特性。 我們來看一下DataType 特性應用於 ReleaseDate 和 Price 屬性。代碼如下。
[Display(Name = "出版日期")] [DataType(DataType.Date)] public DateTime ReleaseDate { get; set; } [Range(1,200)] [DataType(DataType.Currency)] public decimal Price { get; set; }
DataType 特性僅提供相關提示來幫助視圖引擎設置數據格式(例如向 URL 提供 <a> 和向電子郵件提供 <a href="mailto:test@163.com">)。 使用 正則表達式(RegularExpression)特性校驗數據的格式。 DataType 特性用於指定比數據庫內部類型更具體的數據類型。 DataType 特性不是校驗特性。 示例應用程序中“出版日期”僅顯示日期,不顯示時間。
DtaType 枚舉提供了多種數據類型,例如日期、時間、電話號碼、貨幣、電子郵件地址等。 DataType特性的使用能夠使應用程序自動提供特定數據類型的功能。 例如,可為 DataType.EmailAddress 創建 mailto: 鏈接。 如果瀏覽器支持 HTML5 ,DataType.Date類型瀏覽器將提供日期選擇器,如下圖。
DataType 特性發出 HTML 5 特性供 支持HTML 5 瀏覽器使用。 DataType 特性不提供任何校驗。
DataType.Date 不指定顯示日期的格式。 默認情況下,日期數據格式基於服務器的 CultureInfo 的默認格式進行顯示。
DisplayFormat 特性用於顯式指定日期格式:例如
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] public DateTime ReleaseDate { get; set; }
ApplyFormatInEditMode 設置用於指定在顯示值進行編輯時需要顯示的格式。 在某些場景中,您可能不希望某些字段具有此行為。 例如,在貨幣值中,可能不希望編輯 UI 中使用貨幣符號。
可單獨使用 DisplayFormat 特性,但通常建議使用 DataType 特性。 DataType 特性傳遞數據的語義而不是傳遞如何在前端界面上呈現數據,DataType具體 DisplayFormat 不具備的以下優勢:
- 瀏覽器如果支持HTML5,則會自動顯示相應的一些控件與功能(例如顯示日期控件、區域設置適用的貨幣符號、電子郵件鏈接等)。
- 默認情況下,瀏覽器將根據您在區域設置中設置的區域采用正確的格式呈現數據。
- DataType特性可以使ASP.NET Core框架可選擇適當的字段模板來呈現數據。如果單獨使用時,可以使用DisplayFormat 特性的顯式的指定數據格式。
注:jQuery校驗不能校驗日期范圍與日期時間。例如,在Book類中添加下面的代碼,在瀏覽器中輸入任何日期,都是顯示校驗錯誤,即使選擇的日期是在指定的范圍之內,如下圖:
[Display(Name = "出版日期")] [Range(typeof(DateTime), "1980/1/1", "2050/1/1")] public DateTime ReleaseDate { get; set; }
通常,在實體類中設置固定日期是不合適的,因此不推薦使用 Range 特性和 DateTime特性。