MVC - 部分更新视图中的模型
场景如下:我有一个像这样的 User 对象:
public class User : BaseEntity<User>, IAggregateRoot
{
public virtual string Name { get; set; }
public virtual string Username { get; set; }
public virtual string Password { get; set; }
public virtual string SecretQuestion { get; set; }
public virtual string SecretAnswer { get; set; }
public virtual DateTime LastLogin { get; set; }
}
在编辑该对象期间,我将其加载到视图中,但我只想更新一些属性(即我不想更新 LastLogin 属性)。在这种情况下我该怎么办?
创建用户视图模型的最佳策略是,当我尝试使用 null LastLogin 字段更新用户对象时,nhibernate 会处理这个问题吗?
提前致谢。
编辑
是这样的:
public class UserViewModel
{
public string Name {get;set;}
public string UserName {get;set;}
public string Password {get;set;}
public string SecretQuestion {get;set;}
public string SecretAnswer {get;set;}
}
然后是编辑:
public ActionResult Edit(int id)
{
return View(_userRepository.FindById(id));
}
[HttpPost]
public ActionResult Edit(int id, UserViewModel userViewModel)
{
try
{
//Not sure how to update the model
//with the view Model and save.
_userRepository.Update(????);
return RedirectToAction("Index");
}
catch
{
return View();
}
}
Heres the scenario: I have a User object like this:
public class User : BaseEntity<User>, IAggregateRoot
{
public virtual string Name { get; set; }
public virtual string Username { get; set; }
public virtual string Password { get; set; }
public virtual string SecretQuestion { get; set; }
public virtual string SecretAnswer { get; set; }
public virtual DateTime LastLogin { get; set; }
}
During the editing of this object, i load it into the view, but i only want to update some of the properties (ie i wouldnt want to update LastLogin property). In this situation what would i do?
Is the best strategy to create a user viewmodel, and will nhibernate cope with this when i try to update a user object with a null LastLogin field?
Thanks in advance.
EDIT
Something like this:
public class UserViewModel
{
public string Name {get;set;}
public string UserName {get;set;}
public string Password {get;set;}
public string SecretQuestion {get;set;}
public string SecretAnswer {get;set;}
}
And then the editing:
public ActionResult Edit(int id)
{
return View(_userRepository.FindById(id));
}
[HttpPost]
public ActionResult Edit(int id, UserViewModel userViewModel)
{
try
{
//Not sure how to update the model
//with the view Model and save.
_userRepository.Update(????);
return RedirectToAction("Index");
}
catch
{
return View();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
一个好的方法是创建一个仅包含您想要显示/更新的属性的 UserViewModel。不要让 nHibernate 了解视图模型。然后,当编辑被发送回控制器时,您从 nHibernate 检索实际的 User 对象,从视图模型更新其属性,然后将其保存回数据库。
更新
是这样的:
在我最近从事的一个项目中,我创建了一个 ViewModelBase 类,其中包含将属性从域模型映射到视图模型并基于匹配属性名称再次映射回来的方法并键入。我所有的视图模型都源自 ViewModelBase。
还有其他工具,例如 AutoMapper 可以执行此类操作以及更多更多操作。
A good approach is to create a
UserViewModel
with only the properties you want to display/update. Don't let nHibernate know about the view model. Then, when the edits are posted back to your controller you retrieve the actual User object from nHibernate, update it's properties from the view model, and then save it back to the database.Update
Something like this:
In a project I've been working on recently I created a ViewModelBase class which includes methods that maps properties from a domain model to a view model and back again based on matching the property name and type. All my view models are derived from ViewModelBase.
There are other tools like AutoMapper that do this sort of thing and much, much more.
我添加另一个答案,因为还有另一种完全不同的方法。
您只需在视图中使用
User
对象,然后使用TryUpdateModel
指定要在模型中更新的属性。在这种情况下,您不一定需要视图模型。如果您愿意,可以使用它,但并非必须这样做。然后,Post 操作将类似于:
字符串数组是要在模型中更新的属性白名单,控制器尝试更新表单发布数据(和其他源)中的值。由于
LastLogin
不在字符串数组中,因此模型更新时不会触及它。I'm adding another answer, because there is another, completely different, approach.
You can just use your
User
object in your view, and then useTryUpdateModel
to specify the properties to update in the model. You don't necessarily need a view model in this case. You can use one if you want, but you don't have to.The Post action would then look something like:
The string array is a white-list of properties to update in the model, and the controller attempts to update the values from the form post data (and other sources). Because
LastLogin
is not in the string array, it won't be touched in the update of the model.我正在研究一种创建 DefaultModelBinder 的自定义衍生产品的技术。它的工作方式与 @AndrewCooper 发布的白名单方法类似,但是有一点不同。
在我的方法中,我坚持使用一个大的视图模型,它可以有无数的部分视图尝试更新它。在我的例子中,白名单是通知 ViewModel 如何从存储库自动加载自身所需的关键对象标识字段 - 因此,预计部分视图仅包含这些字段他们关心,并且,足够的隐藏字段来充实对象身份(如果从路线或其他方面不能立即明显看出)。
因此,在 POST“模型绑定”阶段,首先绑定身份字段(因此,触发“加载”以立即从数据库充实模型),并且当绑定过程的其余部分完成时,您已经有效地“合并”使用用户提交的数据从数据库中提取的对象..最重要的是(假设您坚持使用 MVC 约定)它现在已经通过了验证。
这使我能够坚持使用教科书上的简单控制器方法......类似......
理论上,我可以将我所有不同的视图指向同一个方法 - 因为它不关心用户数据来自哪里......它都与来自数据库的最新数据,经过验证并保存。
更多信息请参阅我的 StackOverflow 帖子
I am working on a technique where I create a custom derivative of the DefaultModelBinder. It kinda works along the same lines as the white-list approach posted by @AndrewCooper, but, with a twist.
In my approach, I stick with one big honking ViewModel that can have myriad partial Views attempting to update it. The white-list, in my case, are the critical object identity fields needed to inform the ViewModel how it can auto-load itself from the repository - so, it's expected that the Partial views ONLY contain the fields they care about, and, enough hidden fields to flesh out object identity if it isn't immediately apparent from the route or whatever.
Thus, during the POST 'model binding' phase, identity fields are bound first (thus, a 'load' is triggered to immediately flesh the model from the DB) and as the remainder of the binding process completes, you have effectively 'merged' the object pulled from the DB with the user-submitted data.. and on top of that (assuming you've stuck with MVC conventions) it has now been through validation.
This allows me to stick with a textbook simple controller method.. something like..
Theoretically, I could point all my varying views back to this same method - because it cares not where the user data came from.. it all gets merged with the lastest from the DB, validated, and saved all the same.
More info at my StackOverflow post