練習 - 為地址表單新增伺服器端和用戶端的資料驗證
Blazor 可以將表單繫結至應用程式中的模型。 若在這些模型中佈置資料註釋,就可以執行用戶端和伺服器端驗證,而無須撰寫更多程式碼。
當用戶端未輸入名稱和某些地址欄位時,應用程式無法正確下單。 團隊希望增強驗證功能,於其中加入更多欄位。 他們也希望能夠驗證最短長度和字元。
在此練習中,您將替換掉目前的伺服器端驗證,改為使用資料註釋。 您將學習如何管理驗證訊息,以及如何改進現用的驗證支援。 在最後一個步驟中,您將控制表單提交的方式,只有在所有欄位都有效時才會提交表單。
新增資料註釋至 Blazor 模型
在 Visual Studio Code 的 [檔案總管] 中,展開 [模型],然後選取 [Address.cs]。
在類別的頂端新增
System.ComponentModel.DataAnnotations
的參考。using System.ComponentModel.DataAnnotations;
針對每個必要欄位,新增資料註釋。
public class Address { public int Id { get; set; } [Required, MinLength(3), MaxLength(100)] public string Name { get; set; } [Required, MinLength(5), MaxLength(100)] public string Line1 { get; set; } [MaxLength(100)] public string Line2 { get; set; } [Required, MinLength(3), MaxLength(50)] public string City { get; set; } [Required, MinLength(3), MaxLength(20)] public string Region { get; set; } [Required, RegularExpression(@"^([0-9]{5})$")] public string PostalCode { get; set; } }
在 [檔案總管] 中,展開 [頁面],然後選取 [Checkout.razor]。
在結尾的
</EditForm>
標籤上方,新增驗證摘要和資料註釋驗證程式。<ValidationSummary /> <DataAnnotationsValidator /> </EditForm> </div>
在 EditForm 標籤中,將
OnSubmit
參數替換成有效的提交。<EditForm Model=Order.DeliveryAddress OnValidSubmit=PlaceOrder>
您現在可以刪除自訂的伺服器端邏輯,測試地址的有效性。 刪除
@code
區塊中的CheckSubmission
方法。
測試新的資料註釋驗證
在 Visual Studio Code 中按 F5,或選取 [執行] > [開始偵錯]。
嘗試在不輸入任何資訊的情況下訂購一些披薩,然後輸入不完整的資訊。 觀察每個欄位的詳細錯誤訊息。
此互動可改進每個欄位的錯誤檢查,但每個欄位的錯誤將會比其相關的前一個欄位更好。
按 Shift + F5 可阻止應用程式執行。
改進 EditFrom 的錯誤訊息
在 [檔案總管] 中,展開 [頁面],然後選取 [Checkout.razor]。
刪除 Blazor
<ValidationSummary />
元件。<DataAnnotationsValidator /> </EditForm> </div>
在檔案總管中,展開 [共用],然後選取 [AddressEditor.razor]。
在每個欄位下方,新增自訂驗證訊息。
<div class="form-field"> <label>Name:</label> <div> <InputText @bind-Value="Address.Name" /> <ValidationMessage For="@(() => Address.Name)" /> </div> </div> <div class="form-field"> <label>Line 1:</label> <div> <InputText @bind-Value="Address.Line1" /> <ValidationMessage For="@(() => Address.Line1)" /> </div> </div> <div class="form-field"> <label>Line 2:</label> <div> <InputText @bind-Value="Address.Line2" /> <ValidationMessage For="@(() => Address.Line2)" /> </div> </div> <div class="form-field"> <label>City:</label> <div> <InputText @bind-Value="Address.City" /> <ValidationMessage For="@(() => Address.City)" /> </div> </div> <div class="form-field"> <label>Region:</label> <div> <InputText @bind-Value="Address.Region" /> <ValidationMessage For="@(() => Address.Region)" /> </div> </div> <div class="form-field"> <label>Postal code:</label> <div> <InputText @bind-Value="Address.PostalCode" /> <ValidationMessage For="@(() => Address.PostalCode)" /> </div> </div>
在 [檔案總管] 中,展開 [模型],然後選取 [Address.cs]。
為每個欄位的資料註釋新增自訂錯誤訊息。
public class Address { public int Id { get; set; } [Required, MinLength(3, ErrorMessage = "Please use a Name bigger than 3 letters."), MaxLength(100, ErrorMessage = "Please use a Name less than 100 letters.")] public string Name { get; set; } [Required, MinLength(5, ErrorMessage = "Please use an Address bigger than 5 letters."), MaxLength(100, ErrorMessage = "Please use an Address less than 100 letters.")] public string Line1 { get; set; } [MaxLength(100)] public string Line2 { get; set; } [Required, MinLength(3, ErrorMessage = "Please use a City bigger than 3 letters."), MaxLength(50, ErrorMessage = "Please use a City less than 50 letters.")] public string City { get; set; } [Required, MinLength(3, ErrorMessage = "Please use a Region bigger than 3 letters."), MaxLength(20, ErrorMessage = "Please use a Region less than 20 letters.")] public string Region { get; set; } [Required, RegularExpression(@"^([0-9]{5})$", ErrorMessage = "Please use a valid Postal Code with five numbers.")] public string PostalCode { get; set; } }
測試新的資料註釋驗證
在 Visual Studio Code 中按 F5,或選取 [執行] > [開始偵錯]。
地址表單會在包含無效資料的欄位下方,動態顯示錯誤訊息。 此互動會在用戶端上發生,避免客戶輸入不正確的地址。
按 Shift + F5 可阻止應用程式執行。
還原整體錯誤訊息,並停用 [提交] 按鈕
在 [檔案總管] 中,展開 [頁面],然後選取 [Checkout.razor]。
新增
OnInvalidSubmit
參數,為EditForm
元件呼叫ShowError
方法。<EditForm Model=Order.DeliveryAddress OnValidSubmit=PlaceOrder OnInvalidSubmit=ShowError>
新增可更新
isError
屬性的 ShowError 方法。protected void ShowError() { isError = true; }
變更
PlaceOrder
方法來更新isError
和isSubmitting
屬性。async Task PlaceOrder() { isError = false; isSubmitting = true; var response = await HttpClient.PostAsJsonAsync( $"{NavigationManager.BaseUri}orders", OrderState.Order); var newOrderId= await response.Content.ReadFromJsonAsync<int>(); OrderState.ResetOrder(); NavigationManager.NavigateTo($"myorders/{newOrderId}"); }
在 Visual Studio Code 中按 F5,或選取 [執行] > [開始偵錯]。
若客戶嘗試提交的表單無效,將會顯示錯誤訊息。
按 Shift + F5 可阻止應用程式執行。
當所有欄位皆正確時,啟用 [提交] 按鈕
當客戶因為未完成所有欄位而無法提交訂單時,是否能有更好的使用者體驗? 我們可以變更簽出頁面來滿足這項需求。 將 EditForm
變更為使用 EditCoNtext,而不使用模型。
在 [檔案總管] 中,展開 [頁面],然後選取 [Checkout.razor]。
更新
EditFrom
元素。<EditForm EditContext=editContext OnValidSubmit=PlaceOrder>
將按鈕元素變更為使用
isError
參數。<button class="checkout-button btn btn-warning" type="Submit" disabled=@isError>
在
@code
區塊中,為新的EditContext
布林值新增宣告。private EditContext editContext;
初始化含了訂單交貨地址的內容。
protected override void OnInitialized() { editContext = new(Order.DeliveryAddress); editContext.OnFieldChanged += HandleFieldChanged; }
此程式碼也允許在欄位變更時,連結事件處理常式。 在新的處理常式中,您可以檢查模型是否有效,並適當地設定
isError
。private void HandleFieldChanged(object sender, FieldChangedEventArgs e) { isError = !editContext.Validate(); StateHasChanged(); }
因為先前建立了事件處理常式,若簽出元件不再需要該常式,就應加以處置。
public void Dispose() { editContext.OnFieldChanged -= HandleFieldChanged; }
若要實作
Dispose
功能,必須告知 Blazor。 在頁面頂端的@inject
陳述式底下新增此程式碼。@implements IDisposable
刪除所有對
isSubmitting
的參考,並更新PlaceOrder
方法。async Task PlaceOrder() { var response = await HttpClient.PostAsJsonAsync(NavigationManager.BaseUri + "orders", OrderState.Order); var newOrderId= await response.Content.ReadFromJsonAsync<int>(); OrderState.ResetOrder(); NavigationManager.NavigateTo($"myorders/{newOrderId}"); }
在 Visual Studio Code 中按 F5,或選取 [執行] > [開始偵錯]。
現在會提示客戶輸入資訊,而且一開始無法使用 [下單] 按鈕。 當在所有必要欄位中輸入資料之後,就可以點選該按鈕。
按 Shift + F5 可阻止應用程式執行。