2013年2月19日 星期二

ASP.NET MVC - 使用 EditorForModel 編輯資料

EditorForModel,這個用來自動產生 Model 類別編輯內容的 Html Helper 我很少用它,應該說我從來沒有用在專案裡,在 ASP.NET MVC 2 的時候就已經有了,另外還有個專門產生顯示內容的 Html Helper 是 DisplayForModel,有關詳細的介紹可以參閱「ASP.net MVC 4 網站開發美學」作者之一「星寂」在其部落格的其中一篇文章介紹「ASP.NET MVC 2.0 Html.EditorForModel & Html.DisplayForModel」。

會想寫這一篇是因為有人在論壇裡提了一個問題,而這位提問者的程式內容就有用到了 EditForModel,所以我也就來實際操作一番,看看 EditorForModel 使用與不使用有何差異,以及是不是會發生如同那位提問者所遇到的問題。


EditorForModel 方法

http://msdn.microsoft.com/zh-tw/library/system.web.mvc.html.editorextensions.editorformodel%28v=vs.100%29.aspx

image

為頁面所使用的 Model 每一個屬性構建一個編輯器,但因為都是自動對應屬性來產生頁面上 input 的編輯器,所以有些屬性是不需要出現在編輯頁面上的,如果沒有加以設定的話就會自動產生在頁面上了,例如 ID 等。

 

例如說我們有以下這麼一個 SomeThing 類別,

public class SomeThing
{
    [Display(Name = "編號")]
    [Required(ErrorMessage = "請輸入編號")]
    public string ID
    {
        get;
        set;
    }
    [Display(Name = "名稱")]
    [Required(ErrorMessage = "請輸入名稱")]
    [StringLength(100, MinimumLength = 2, ErrorMessage = "名稱字串長度為 10 ~ 100")]
    public string Name
    {
        get;
        set;
    }
    [Display(Name = "類別")]
    [Required(ErrorMessage = "請輸入類別")]
    public string Category
    {
        get;
        set;
    }
}

如果我們要建立這個 SomeThing 類別的編輯頁面時,通常我們會直接使用加入檢視的介面來直接產生 Edit 頁面,

SNAGHTML2dcbae4

如此就會自動幫我們建立一個 Edit 頁面,

image

執行的頁面內容,

image

將頁面上 input 的資料 POST 到後端是沒有任何問題的,

image

 

而如果頁面裡各個屬性的 Html Helper 改以 EditorForModel 來代替呢?修改如下:

image

而 Edit 頁面執行結果,

image

Edit 頁面上多出現了一個編號欄位,而這個編號欄位並不需要讓使用者可以去編輯到,所以我們就要去修改 SomeThing 類別,在上面使用加入檢視介面產生 Edit 頁面,編號這個屬性是自動使用 HiddenFor 的 Html Helper,所以我們可以在 SomeThing 類別中的 ID 屬性加上 [HiddenInput(DisplayValue = false)] 標籤,

image

修改後所產生的 Edit 頁面結果,不會再顯示 ID 編號的欄位,

image

ID 編號欄位為 Hidden Input 欄位,

image

如此一來把編輯後的頁面資料傳送到後端也可以有正確的 Model Binding,

image

 

講到 HiddenInputAttribute 類別,一定會有人想說是不是也可以用 ScaffoldColumnAttribute 類別,並設定 Scaffold 為 false,這樣也可以讓 Edit 頁面不會顯示 ID 編號欄位,例如我們把 SomeThing 類別再做以下的修改,

image

這樣修改後,Edit 頁面上還是一樣使用 EditorForModel 輔助方法,而頁面執行結果也不會出現 ID 編號,但 Html Code 也將不會帶出 ID 編號資料,

image

image

這麼一來,把 Edit 頁面上的資料 POST 到後端,ModelState 的檢查依然是正確的,這是因為我們在 View 頁面裡所使用的 Html.BeginForm() 為預設的,會自動帶入當前的網址以及 QueryString,因為 QueryString 有包含 ID 值,所以 Model Binding 時就會把 ID 值給帶入到 Model 當中,

image

image

 

如果我們把 Html.BeginForm() 修改如下,會有什麼樣的結果呢?

image

執行後的頁面與 Html Code,

image

image

因為沒有任何的 ID 編號資料值傳入,所以 ModelState.IsValid 就會檢查為錯誤,

image

image

 

最後,如果 SomeThing 類別的 ID 屬性改用 HiddenInput(DisplayValue = false) 並且使用 Html.BeginForm("EditForSomeThing", "Home", FormMethod.Post) 呢?

image

因為傳送到後端的 Model 資料都沒有遺漏,所以 ModelState.IsValid 為 true 的。

image

 

所以在設定上要多方留意,並且小心檢查各個欄位是否有任何的缺漏,要不然一個不經意的修改,往往就會讓我們找錯找到抓狂。

最後我還是會建議大家就腳踏實地一點,要使用 EditorForModel 就不要偷懶,最好是搭配建立好的 Template 來使用,不要貪圖一時方便而直接使用 EditorForModel,使得太多頁面上的元素都因為自動產生而衍生更多的問題。

 

延伸閱讀:

MSDN - EditorExtensions.EditorForModel 方法
http://msdn.microsoft.com/zh-tw/library/system.web.mvc.html.editorextensions.editorformodel%28v=vs.100%29.aspx

MSDN - HiddenInputAttribute 類別
http://msdn.microsoft.com/zh-tw/library/ee470818%28v=vs.100%29.aspx

MSDN - ScaffoldColumnAttribute 類別
http://msdn.microsoft.com/zh-tw/library/cc679283%28v=vs.100%29.aspx

C#Corner - ScaffoldColumn(bool value) vs HiddenInput(DisplayValue = bool value) in MVC
http://www.c-sharpcorner.com/UploadFile/54db21/scaffoldcolumnbool-value-vs-hiddeninputdisplayvalue-boo/

 

以上

沒有留言:

張貼留言

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。