使用Controller.UpdateModel方法来更新ViewModel
2011-09-11 13:10 Fred-Xu 阅读(4925) 评论(1) 收藏 举报
在MVC中,更新Model的时候,我们通常使用Controller.UpdateModel方法。我最近在项目中使用了自定义ViewModel,在使用UpdateModel方法的时候无法映射到Post的数据到Model对象里。这个解决方案是一个简单的,但并不像它应该的IntelliSense不拾取方法的重载泛型类型推断时。
当不使用ViewModel的时候,我可以像这样使用Controller方法:
1 2 3 4 5 6 | public ActionResult Edit( int id) { Student student = context.Student.FirstOrDefault(s => s.ID.Equals(id)); return View(student); } |
前端View中使用强类型视图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <div> <%= Html.LabelFor(model => model.Forename) %> </div> <div> <%= Html.TextBoxFor(model => model.Forename)%> <%= Html.ValidationMessageFor(model => model.Forename)%> </div> <div> <%= Html.LabelFor(model => model.Surname)%> </div> <div> <%= Html.TextBoxFor(model => model.Surname)%> <%= Html.ValidationMessageFor(model => model.Surname)%> </div> |
Controller中可以用这样的方法来保存Student数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | [HttpPost] public ActionResult Edit( int id, FormCollection formValues) { try { Student student = context.Student.FirstOrDefault(s => s.ID.Equals(id)); UpdateModel(student); context.SaveChanges(); return RedirectToAction( "Details" , new { id = student.ID }); } catch { throw ; } } |
UpdateModel会遍历formValues集合并且映射post过来的数据到student model对象中。如果我去检查这个集合的Keys,我可以看到formValues匹配了student model的属性,使得映射成功。
现在来看看如果使用ViewModel会发生什么,这是一个很好的MVC练习。
下面是一个Student ViewModel的代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class StudentModel { public Student Student { get ; set ; } public SelectList Titles { get ; set ; } public StudentModel() { } public StudentModel(Student student, IEnumerable<Title> titles) { Student = student; Titles = new SelectList(titles, "ID" , "Name" , student.TitleID); } } |
接下来是如何使用ViewModel来编辑的方法:
1 2 3 4 5 6 | public ActionResult Edit( int id) { Student student = context.Student.FirstOrDefault(s => s.ID.Equals(id)); return View( new StudentModel(student, context.Title)); } |
前端View视图页代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | < div > <%= Html.LabelFor(model => model.Student.Title) %> </ div > < div > <%= Html.DropDownListFor(model => model.Student.TitleID, Model.Titles)%> </ div > < div > <%= Html.LabelFor(model => model.Student.Forename) %> </ div > < div > <%= Html.TextBoxFor(model => model.Student.Forename)%> <%= Html.ValidationMessageFor(model => model.Student.Forename)%> </ div > |
我们设断点来看下这次Post到Edit方法的formValues集合,Keys如图所示:
可以看到Keys中包含了Student这个Model对象,这是因为ViewModel使用了这个Student Model,但增加了“Student”作为前缀,和前面直接使用Model不一样。如果按照前面的UpdateModel方法,程序会获取不到post过来的值,也会报错。在这里,UpdateModel有重载方法,第二参数是Prefix,也就是"Student"前缀。
我们这下写这个UpdateModel方法:
1 | UpdateModel<Student>(student, "Student" ); |
你可以看到使用了“Student”作为前缀,映射正确。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | [HttpPost] public ActionResult Edit( int id, FormCollection formValues) { try { Student student = context.Student.FirstOrDefault(s => s.ID.Equals(id)); UpdateModel(student, "Student" ); context.SaveChanges(); return RedirectToAction( "Details" , new { id = student.ID }); } catch { throw ; } } |
程序运行成功!
特别注意:在增加了Prefix后,如果Post过来Form中有不等于Prefix的Name,UpdateModel的时候会报错。一旦增加Prefix前缀后,Post过来的FormCollection必须都含有该前缀对象才可以Work。
希望该文章会给大家带来帮助!
【推荐】2025 HarmonyOS 鸿蒙创新赛正式启动,百万大奖等你挑战
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】开源 Linux 服务器运维管理面板 1Panel V2 版本正式发布
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 别做抢活的导演:代码中的抽象层次原则
· 从 Redis 客户端超时到 .NET 线程池挑战
· C23和C++26的#embed嵌入资源指南
· 「EF Core」框架是如何识别实体类的属性和主键的
· 独立开发,这条路可行吗?
· 他没买 iPad,而是花了半年时间,为所有“穷学生”写了个笔记神器
· Visual Studio 现已支持新的、更简洁的解决方案文件(slnx)格式
· 从 Redis 客户端超时到 .NET 线程池挑战:饥饿、窃取与阻塞的全景解析
· 2025年中总结:我想我克服公众演讲的恐惧了,一个社恐分子突破自我的故事
· 3.1k star!推荐一款开源基于AI实现的浏览器自动化插件工具 !
2009-09-11 Js获取Gridview中模板列控件ID,获取控件生成的HTML中的ID