前言
第一篇說明了 TryUpdateModel 的簡單的應用,除了可指定更新的欄位之外也可排除更新特定的欄位,而因為可搭配 Metadata 做欄位驗證為資料又做了一層把關,但在 ASP.NET MVC 中我們也很常針對每個的頁面(View)定義專屬的 ViewModel ,而若照個第一篇的寫法會發現欄位無法正確繫結,所以這篇就來教大家如何正確利用 TryUpdateModel 來為我們的 ViewModel 做資料更新 ~
說明
首先我們先定義一個 ViewModel 如下:
public class ProductViewModel { public Product ViewProduct { get; set; } }
透過 ViewModel 所產生的 View 如下:
@model MvcTemplete.Models.ProductViewModel @{ ViewBag.Title = "Edit"; } @using (Html.BeginForm()) { @Html.ValidationSummary(true) <fieldset> <legend>Product</legend> @Html.HiddenFor(model => model.ViewProduct.ProductId) <div class="editor-label"> @Html.LabelFor(model => model.ViewProduct.Name) </div> <div class="editor-field"> @Html.EditorFor(model => model.ViewProduct.Name) @Html.ValidationMessageFor(model => model.ViewProduct.Name) </div> <div class="editor-label"> @Html.LabelFor(model => model.ViewProduct.Ename) </div> <div class="editor-field"> @Html.EditorFor(model => model.ViewProduct.Ename) @Html.ValidationMessageFor(model => model.ViewProduct.Ename) </div> <div class="editor-label"> @Html.LabelFor(model => model.ViewProduct.ModifyUid) </div> <div class="editor-field"> @Html.EditorFor(model => model.ViewProduct.ModifyUid) @Html.ValidationMessageFor(model => model.ViewProduct.ModifyUid) </div> <p> <input type="submit" value="Save" /> </p> </fieldset> } </span>
接下來我們先看看 Post 回 Controller 時 FormCollection 所接收到集合,如下:
由上圖可看到在每個 Key 中包含了 ViewProduct 這個前置詞,因為在 ViewModel 裡我們使用了 Prodcut 這個 Model 且命名為 ViewProduct,如果讀者照著上一篇的 TryUpdateModel 的方法,程式會無法成功繫結。
此時我們可以利用 TryUpdateModel 的另外一個多載來達到資料繫結,程式碼如下:
if(TryUpdateModel(product, "ViewProduct")) { db.SaveChanges(); }
而若希望更新特定欄位或排除特定欄位,如下:
if(TryUpdateModel(product, "ViewProduct",new string[] {"Name"},new string[] {"ModifyUid"})) { db.SaveChanges(); }
上面的執行結果僅會更新 Name 欄位,而排除更新 ModifyUid 這個欄位。
當然上面的方法還是不夠完美,因為我們並沒有搭配 FormCollection 來做資料繫結並排除特定欄位 ,但因為 FormCollection 內的 Keys 是有加上前置詞,導致無法成功繫結並更新,這部份筆者有寫了個轉換的Code來去掉前置詞,如下:
var Keys = formValue.AllKeys; List<string> newKeys = new List(); foreach (var item in Keys) { newKeys.Add(item.Replace("ViewProduct.", "")); } if (TryUpdateModel(product, "ViewProduct", newKeys.ToArray(), new string[] { "ModifyUid" })) { db.SaveChanges(); }</string>
OK !大功告成 ~ 不過不知道有沒有其他大大能針對 FormCollection 有前置詞的部份能有其他更好的解法,因為這個解法只是單純去做字串取代而已(逃)。
總結
只能說 TryUpdateModel 在實務上的應用太強大了,如果能善加利用其提供的多載鐵定能應用各種不同的需求,當然還是提醒一下大家使用 TryUpdateModel 時還是要加入「黑名單」或「白名單」,來讓我們的資料更加正確!