请选择 进入手机版 | 继续访问电脑版
查看: 496|回复: 0

[.NET源码] ASP.NET MVC利用TryUpdateModel来做资料更新 (二) ViewModel篇

3万

主题

3万

帖子

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
100197
发表于 2015-11-19 18:07:04

前言
第一篇说明了 ASP.NET MVC利用TryUpdateModel来做资料更新 (一) 的简单的应用,除了可指定更新的字段之外也可排除更新特定的字段,而因为可搭配 Metadata 做字段验证为数据又做了一层把关,但在 ASP.NET MVC 中我们也很常针对每个的页面(View)定义专属的 ViewModel ,而若照个第一篇的写法会发现字段无法正确系结,所以这篇就来教大家如何正确利用 TryUpdateModel 来为我们的 ViewModel 做数据更新 ~

说明
首先我们先定义一个 ViewModel 如下:

public class ProductViewModel
{
public Product ViewProduct { get; set; }
}

通过 ViewModel 所产生的 View 如下:


  1. @model MvcTemplete.Models.ProductViewModel
  2. @{
  3. ViewBag.Title = "Edit";
  4. }
  5. @using (Html.BeginForm())
  6. {
  7. @Html.ValidationSummary(true)
  8. <fieldset>
  9. <legend>Product</legend>
  10. @Html.HiddenFor(model => model.ViewProduct.ProductId)
  11. <div class="editor-label">
  12. @Html.LabelFor(model => model.ViewProduct.Name)
  13. </div>
  14. <div class="editor-field">
  15. @Html.EditorFor(model => model.ViewProduct.Name)
  16. @Html.ValidationMessageFor(model => model.ViewProduct.Name)
  17. </div>
  18. <div class="editor-label">
  19. @Html.LabelFor(model => model.ViewProduct.Ename)
  20. </div>
  21. <div class="editor-field">
  22. @Html.EditorFor(model => model.ViewProduct.Ename)
  23. @Html.ValidationMessageFor(model => model.ViewProduct.Ename)
  24. </div>
  25. <div class="editor-label">
  26. @Html.LabelFor(model => model.ViewProduct.ModifyUid)
  27. </div>
  28. <div class="editor-field">
  29. @Html.EditorFor(model => model.ViewProduct.ModifyUid)
  30. @Html.ValidationMessageFor(model => model.ViewProduct.ModifyUid)
  31. </div>
  32. <p>
  33. <input type="submit" value="Save" />
  34. </p>
  35. </fieldset>
  36. }
  37. </span>
复制代码

接下来我们先看看 Post 回 Controller 时 FormCollection 所接收到集合,如下:


由上图可看到在每个 Key 中包含了 ViewProduct 这个前置词,因为在 ViewModel 里我们使用了 Prodcut 这个 Model 且命名为 ViewProduct,如果读者照着上一篇的 ASP.NET MVC利用TryUpdateModel来做资料更新 (一) 的方法,程序会无法成功系结。

此时我们可以利用 TryUpdateModel 的另外一个多载来达到数据系结,程序代码如下:

if(TryUpdateModel(product, "ViewProduct"))
{
db.SaveChanges();
}

而若希望更新特定字段或排除特定字段,如下:

if(TryUpdateModel(product, "ViewProduct",new string[] {"Name"},new string[] {"ModifyUid"}))
{
db.SaveChanges();
}

上面的执行结果仅会更新 Name 字段,而排除更新 ModifyUid 这个字段。www.it165.net


当然上面的方法还是不够完美,因为我们并没有搭配 FormCollection 来做数据系结并排除特定字段 ,但因为 FormCollection 内的 Keys 是有加上前置词,导致无法成功系结并更新,这部份笔者有写了个转换的Code来去掉前置词,如下:

  1. var Keys = formValue.AllKeys;
  2. List newKeys = new List();
  3. foreach (var item in Keys)
  4. {
  5. newKeys.Add(item.Replace("ViewProduct.", ""));
  6. }
  7. if (TryUpdateModel(product, "ViewProduct", newKeys.ToArray(), new string[] { "ModifyUid" }))
  8. {
  9. db.SaveChanges();
  10. }
复制代码

OK !大功告成 ~ 不过不知道有没有其它大大能针对 FormCollection 有前置词的部份能有其它更好的解法,因为这个解法只是单纯去做字符串取代而已(逃)。

总结
只能说 TryUpdateModel 在实务上的应用太强大了,如果能善加利用其提供的多载铁定能应用各种不同的需求,当然还是提醒一下大家使用 TryUpdateModel 时还是要加入「黑名单」或「白名单」,来让我们的数据更加正确!



回复

使用道具 举报