無須撰寫驗證程式碼,就能間接驗證使用者輸入
- 5 分鐘
您在表單中,指示網站使用者如何正確地完成每項值,同時您也必須檢查他們所輸入的值。 Blazor 提供簡單的工具,只需要撰寫一些基本的自訂程式碼,就能執行此項驗證。
在本單元中,您將瞭解如何標註模型,讓 Blazor 知道預期的數據。 您也會瞭解如何設定表單,以便正確驗證及回應用戶數據。
驗證 Blazor 表單中的使用者輸入
當您從網站使用者收集資訊時,檢查資訊及其格式的正確性很重要:
- 基於商務原因:電話號碼或訂單詳細數據等客戶信息必須正確,才能為使用者提供良好的服務。 例如,您的網頁若能可以在使用者輸入電話號碼時,即使發現格式錯誤,就能日後因為延遲而衍生高額的費用。
- 基於技術原因:如果您的程式代碼使用窗體輸入進行計算或其他處理,不正確的輸入可能會導致錯誤和例外狀況。
- 基於安全性考慮:惡意使用者可能會嘗試利用未檢查的輸入欄位來插入程序代碼。
網站使用者知道驗證規則會確認其身分,以及其輸入之資料格式的正確性。 必要欄位通常會以星號或 必要 標籤示。 如果他們省略值或輸入格式不佳的值,他們會看到驗證訊息,指示他們如何更正問題。 當使用者離開欄位或選取提交按鈕時,可能會顯示驗證訊息。
以下是使用者提交無效數據的範例表單。 在此範例中,驗證訊息顯示在表單底部,不正確欄位則以紅色醒目提示。 您將在下一個練習中建置這份表單:
驗證訊息的內容應盡可能提供實質的幫助。 請勿假設使用者懂得所有事情;例如不一定所有人都知道正確的電子郵件格式。
當您在 Blazor 中使用 EditForm 元件時,您有各種不同功能的選項可以使用,而無須撰寫複雜的程式碼:
- 在您的模型中,您可以針對每個屬性使用 數據批注 ,告訴 Blazor 值何時需要,以及它們應該採用的格式。
- 在您的
EditForm元件中,新增 DataAnnotationsValidator 元件,它會根據使用者的輸入值檢查模型批注。 - 當您想要在提交表單中顯示所有驗證訊息的摘要時,請使用 ValidationSummary 元件。
- 當您想要顯示特定模型屬性的驗證訊息時,請使用 ValidationMessage 元件。
準備模型進行驗證
首先,告知 DataAnnotationsValidator 元件有效數據的外觀。 您可以在資料模型中,使用註釋屬性宣告驗證限制。 請考慮此範例:
using System.ComponentModel.DataAnnotations;
public class Pizza
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
[EmailAddress]
public string ChefEmail { get; set;}
[Required]
[Range(10.00, 25.00)]
public decimal Price { get; set; }
}
我們以一種讓 Blazing Pizza 人員可以將新的披薩加入菜單的形式使用此模型。 模型中包含 [Required] 屬性,可確保 Name 和 Price 值必能完成。 此外也使用 [Range] 屬性,檢查輸入的價格是否落在披薩的合理範圍內。 最後使用 [EmailAddress] 屬性,檢查輸入的 ChefEmail 值,是有效的電子郵件地址。
您可以在模型中使用的其他註釋包括:
[ValidationNever]:當您想要確保該欄位永遠不會包含在驗證中時,請使用此註釋。[CreditCard]:當您想要記錄使用者的有效信用卡號碼時,請使用此註釋。[Compare]:當您想要確保模型中的兩個屬性相符時,請使用此註釋。[Phone]:當您想要記錄使用者的有效電話號碼時,請使用此註釋。[RegularExpression]:使用此註釋以透過將值與規則運算式進行比較來檢查該值的格式。[StringLength]:使用此註釋來檢查字串值的長度是否超過最大長度。[Url]:當您想要記錄使用者的有效 URL 時,請使用此註釋。
Note
比較字串與模式,以及修改字串時,大多會使用規則運算式。 您可以使用規則算式定義表單值必須依循的自訂格式。 若要深入瞭解 .NET 中的正則表達式,請參閱 .NET 正則表示式。
新增驗證元件至表單
若要將表單設定為使用數據批註驗證,請先確定輸入控件已系結至模型屬性。 然後,在元件內某處新增EditForm元件。 若要顯示驗證產生的訊息,請使用 ValidationSummary 元件,以顯示表單中所有控件的所有驗證訊息。 如果您想要在每個控件旁邊顯示驗證訊息,請使用多個 ValidationMessage 元件。 請記得使用 屬性,將每個 For 控件系結至模型的特定屬性:
@page "/admin/createpizza"
<h1>Add a new pizza</h1>
<EditForm Model="@pizza">
<DataAnnotationsValidator />
<ValidationSummary />
<InputText id="name" @bind-Value="pizza.Name" />
<ValidationMessage For="@(() => pizza.Name)" />
<InputText id="description" @bind-Value="pizza.Description" />
<InputText id="chefemail" @bind-Value="pizza.ChefEmail" />
<ValidationMessage For="@(() => pizza.ChefEmail)" />
<InputNumber id="price" @bind-Value="pizza.Price" />
<ValidationMessage For="@(() => pizza.Price)" />
</EditForm>
@code {
private Pizza pizza = new();
}
控制應用程式的表單驗證
Blazor 會在下列兩個不同的時機執行驗證:
- 當使用者跳出欄位時,就會執行欄位驗證。 欄位驗證可確保使用者在第一時間知道驗證問題。
- 當使用者提交表單時,會執行模型驗證。 模型驗證可確保不會儲存到不正確的資料。
當表單驗證失敗時,訊息會顯示在 ValidationSummary 和 ValidationMessage 元件中。 若要自訂這些訊息,可以將屬性新增 ErrorMessage 屬性至模型中每個欄位的資料註釋:
public class Pizza
{
public int Id { get; set; }
[Required(ErrorMessage = "You must set a name for your pizza.")]
public string Name { get; set; }
public string Description { get; set; }
[EmailAddress(ErrorMessage = "You must set a valid email address for the chef responsible for the pizza recipe.")]
public string ChefEmail { get; set;}
[Required]
[Range(10.00, 25.00, ErrorMessage = "You must set a price between $10 and $25.")]
public decimal Price { get; set; }
}
內建的驗證屬性有多種用途,您可以使用規則運算式檢查許多種文字模式。 若您有特定或獨特的驗證需求,內建屬性可能無法完全符合您的需要。 此時,您可以建立自訂驗證屬性。 首先,請先建立一個繼承自 ValidationAttribute 類別的類別,然後覆寫 IsValid 方法:
public class PizzaBase : ValidationAttribute
{
public string GetErrorMessage() => $"Sorry, that's not a valid pizza base.";
protected override ValidationResult IsValid(
object value, ValidationContext validationContext)
{
if (value != "Tomato" || value != "Pesto")
{
return new ValidationResult(GetErrorMessage());
}
return ValidationResult.Success;
}
}
之後在模型類別中,您就能像使用內建屬性般地,使用您的自訂屬性:
public class Pizza
{
public int Id { get; set; }
[Required(ErrorMessage = "You must set a name for your pizza.")]
public string Name { get; set; }
public string Description { get; set; }
[EmailAddress(
ErrorMessage = "You must set a valid email address for the chef responsible for the pizza recipe.")]
public string ChefEmail { get; set;}
[Required]
[Range(10.00, 25.00, ErrorMessage = "You must set a price between $10 and $25.")]
public decimal Price { get; set; }
[PizzaBase]
public string Base { get; set; }
}
當表單提交時,於伺服器端處理表單驗證
當您使用 EditForm 元件時,有三個事件可以用於回應表單提交:
OnSubmit:無論驗證的結果如何,只要使用者提交表單,就會引發此事件。OnValidSubmit:當使用者提交表單,而且輸入通過驗證時,就會引發此事件。OnInvalidSubmit:當使用者提交表單,但輸入驗證失敗時,就會引發此事件。
如果您使用 OnSubmit,其他兩個事件不會引發。 反之,您可以使用 EditContext 參數,檢查是否要處理輸入資料。 當您想要撰寫自己的邏輯處理表單提交時,可使用此事件:
@page "/admin/createpizza"
<h1>Add a new pizza</a>
<EditForm Model="@pizza" OnSubmit=@HandleSubmission>
<DataAnnotationsValidator />
<ValidationSummary />
<InputText id="name" @bind-Value="pizza.Name" />
<ValidationMessage For="@(() => pizza.Name)" />
<InputText id="description" @bind-Value="pizza.Description" />
<InputText id="chefemail" @bind-Value="pizza.ChefEmail" />
<ValidationMessage For="@(() => pizza.ChefEMail)" />
<InputNumber id="price" @bind-Value="pizza.Price" />
<ValidationMessage For="@(() => pizza.Price" />
</EditForm>
@code {
private Pizza pizza = new();
void HandleSubmission(EditContext context)
{
bool dataIsValid = context.Validate();
if (dataIsValid)
{
// Store valid data here
}
}
}
若改用 OnValidSubmit 和 OnInvalidSubmit,就無須檢查每個事件處理常式中的驗證狀態:
@page "/admin/createpizza"
<h1>Add a new pizza</a>
<EditForm Model="@pizza" OnValidSubmit=@ProcessInputData OnInvalidSubmit=@ShowFeedback>
<DataAnnotationsValidator />
<ValidationSummary />
<InputText id="name" @bind-Value="pizza.Name" />
<ValidationMessage For="@(() => pizza.Name)" />
<InputText id="description" @bind-Value="pizza.Description" />
<InputText id="chefemail" @bind-Value="pizza.ChefEmail" />
<ValidationMessage For="@(() => pizza.ChefEMail)" />
<InputNumber id="price" @bind-Value="pizza.Price" />
<ValidationMessage For="@(() => pizza.Price" />
</EditForm>
@code {
private Pizza pizza = new();
void ProcessInputData(EditContext context)
{
// Store valid data here
}
void ShowFeedback(EditContext context)
{
// Take action here to help the user correct the issues
}
}