2.8 資料標記屬性與表單驗證

ASP.NET MVC 實務精要|第二章 表單

資料無論新增或是修改之前,都必須經過驗證才能正式儲存至資料庫,MVC提供了資料模型層級的驗證設定,集中驗證規則的處理,透過資料標記屬性設定即可嵌入相關的驗證功能。
以下列舉可供設定的資料標記屬性:

標記屬性
說明
Required
指定屬性為必要欄位。
DisplayName
表單欄位上所要顯示的文字與驗證訊息。
StringLength
字串欄位上允許的最大文字長度。
Range
數字欄位允許接受的數字範圍。
Bind
參數或是表單值繫結至模型屬性的設定。
ScaffoldColumn
是否顯示欄位值。 

以下針對其中各項驗證屬性進行設定說明,開啟Models/Item.cs修改各資料屬性內容

public class Item
{
[DisplayName("編號")]
public int ItemId { get; set; }
[DisplayName("品項名稱")]
[Required(ErrorMessage = "必須指定品項名稱")]
    [StringLength(20)]
    public string Name { get; set; }
    [DisplayName("品項描述")]
    public string Description { get; set; }
    [DisplayName("品項價格")]
    [Range(99, 1999)]
    public int Price { get; set; }
}

所有的屬性均設定了Display標記,後方的字串參數表示欄位在網頁上所要呈現的標籤名稱。Name 屬性的Required 標記表示此欄位一定要輸入,若使用者沒有輸入則顯示後方 ErrorMessage 指定的錯誤訊息。最後的 Price 屬性為 int 數字型態,因此設定 Range 標記,並指定可輸入的範圍,第一個參數 99 為最小值 ,第二個參數 999 為最大值,如果輸入的值不在這個範圍,則顯示預設的提醒訊息。

重新編譯更新資料庫,接下來開啟Views/Item/Index.cshtml 檢視檔案,修改如下:

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>新增商品資料</legend>
        <div class="editor-field">
            @Html.LabelFor(model => model.Name)
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.LabelFor(model => model.Price)
            @Html.EditorFor(model => model.Price)
            @Html.ValidationMessageFor(model => model.Price)
        </div>
        <div class="editor-field">
            @Html.LabelFor(model => model.Description)
            @Html.EditorFor(model => model.Description)
        </div>
        <p>
            <input type="submit" value="新增" />
        </p>
    </fieldset>
}

要在網頁上顯示 DisplayName 標記所指定的參數名稱,設定 @Html.LabelFor() 並指定對應的類別屬性欄位,例如其中這一行:

@Html.LabelFor(model => model.Name) 

這會在網頁上顯示「品項名稱」,其它欄位類推。而在 Price 與 Name 欄位的部份,由於設定了Required與Range,如果沒有輸入資料或是輸入的數字範圍不符,則會顯示相關的錯誤訊息,因此透過@Html.ValidationMessageFor顯示其對應的訊息內容。

表單欄位驗證

除了表單元素的建立,表單的輸入欄位必須進一步提供驗證功能,以規範使用者的資料輸入行為,MVC 在這一方面提供了內建的支援,這一節首先來看ModelState,回到稍早討論的FormsController.cs 控制器,調整其中的FormData()方法內容如下 :

[HttpPost]
public ActionResult FormData(FormCollection formCollection)
{
    // 取出表單欄位值
    if (formCollection["Name"] == null || formCollection["Name"].Length ==0 )
    {
        ModelState.AddModelError("XName", "名稱欄位不可為空值");
    }
    else
    {
        ViewData["Name"] = (formCollection["Name"] == null).ToString();
        ViewData["Email"] = formCollection["Email"];
        ViewData["Phone"] = formCollection["Phone"];
    }
    return View();
}

假設Name欄位是必要值,以網底標示的部份,檢視 Name 欄位是否輸入任何值,沒有的話,表示這個欄位出現了輸入錯誤。引用ModelState 的AddModelError()方法,於其中指定兩個參數,第一個參數為錯誤項目的識別key值,第二個參數則是針對此錯誤所要顯示的訊息,完成設定之後,接下來開啟對應的檢視檔案FormData.cshtml,於其中配置底下的程式碼:

@if (ViewData.ModelState["XName"] != null)
{
    @ViewData.ModelState["XName"].Errors[0].ErrorMessage
}
else if (ViewData["Name"] != null)
{
    <p>您的基本資料如下:</p>
    // 顯示表單內容
else
{
    using (Html.BeginForm())
    {
        // 表單欄位標籤
    }
}

以網底標示的片段判斷是否回傳錯誤訊息,前述於控制器中引用ModelState 的AddModelError()方法加入的第一個參數被當作鍵值,ViewData.ModelState["XName"] 回傳可能加入的訊息文字,由於加入的訊息文字可能不止一個,因此這是一個集合物件,Errors 可以將其全部取回,這個範例僅加入一個「名稱欄位不可為空值」,因此取出索引值為 0 的內容項目,而ErrorMessage則將其內容文字取出。

重新瀏覽網頁,不輸入任何資料,直接按一下「傳送」按鈕,由於沒有輸入資料,因此回傳預先設定的錯誤訊息。

開發實作中,我們通常會儘量讓檢視保留資料呈現的功能而不加入過多的邏輯程式碼,.NET 另外於提供了一組驗證專屬的API Data Annotations ,以屬性標示的方式支援資料的驗證工作,簡化驗證功能的設計,後續文章進行討論。

沒有留言: