前言
有使用 ASP.NET MVC 的朋友们一定多多少少有听过 TryUpdateModel,之前就看了很多有关它的文章,但在专案实务上都未曾实际使用过,而 TryUpdateModel 不仅能利用 Metadata 来做栏位验证确保资料正确性,也可以指定更新的条件或是指定某几个栏位不更新,这几天刚好有时间就写了简单的范例,来看看它到底有什么神奇魔力吧。
说明
首先我们先定义一个 Model 如下:
一般透过 TryUpdateModel 来做资料更新,最简单的写法如下 :
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Edit(int Id) { Product product = db.Product.Where(p => p.Id.Equals(Id)).FirstOrDefault(); if (TryUpdateModel(product, new string[] { "Name", "Ename", "ModifyUid" })) { db.SaveChanges(); return RedirectToAction("Index"); } return View(product); }
在 TryUpdateModel 里的第一个参数为要被更新的资料,而第二个参数则是我们要细节的资料,这时候可能会有个疑问,那它细节的资料是从哪边而来的?「其实就跟 Model Binding 的机制很像,TryUpdateModel 会透过你从表单回传的资料,只要名称一样就会自己系节上去啰。」
所以透过上面的程式码,只会更新 Name、Ename、ModifyUid 这三个栏位,其他栏位的资料是不会做更新的。www.it165.net
但如果今天我们页面上的栏位有十几二十个的的话,若使用上面的方法光打栏位名称可能就会花费许多时间!
此时我们可以利用 FormCollection 来接收 View 传来的资料来做栏位更新,所以可以改成以下写法:
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Edit(int Id, FormCollection FromValue) { Product product = db.Product.Where(p => p.Id.Equals(Id)).FirstOrDefault(); if (TryUpdateModel(product, FromValue.AllKeys) && ModelState.IsValid) { db.SaveChanges(); return RedirectToAction("Index"); } return View(product); }
但问题又来了,一般情况下总是会有某些栏位是不希望使用者去做更新的,则透过 TryUpdateModel 的多载来达到排除栏位的效果,如下:
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Edit(int Id, FormCollection FromValue) { Product product = db.Product.Where(p => p.Id.Equals(Id)).FirstOrDefault(); if (TryUpdateModel(product, "", FromValue.AllKeys, new string[] { "ModifyUid" })) { db.SaveChanges(); return RedirectToAction("Index"); } return View(product); }
如上面的程式片段,我们可以排除更新 ModifyUid 的栏位。
总结
TryUpdateModel 拥有了10个多载的方法,所以它可以应用的范围也非常广,但在使用上也有需要注意的地方,像是其第一个多载方法就存在着「安全性问题」,因为预设是接收 View 所传来的资料来做资料系结,只要是符合的栏位就会直接写入 Model 中,所以当你有某些栏位是不想给使用者更新时,请务必设定「白名单」或「黑名单」!