在 MVC 中仅更新对象的某些字段的最佳方法是啥?
Posted
技术标签:
【中文标题】在 MVC 中仅更新对象的某些字段的最佳方法是啥?【英文标题】:What is the best way to update only some fields of an object in MVC?在 MVC 中仅更新对象的某些字段的最佳方法是什么? 【发布时间】:2015-09-01 03:14:19 【问题描述】:我正在尝试更新新闻帖子。该帖子有一个名为 Created 的日期字段,该字段在最初创建记录时填充。我在更新的时候没有包含这个,所以当使用下面的方法时,这个为空并且会抛出一个错误。
我正在使用 MVC 5 和实体框架 6
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id,Title,Summary,Content")] Post post)
if (ModelState.IsValid)
db.Entry(post).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
return View(post);
此方法确实有效,但似乎有点笨拙。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id,Title,Summary,Content")] Post post)
if (ModelState.IsValid)
var newsPost = db.Posts.Find(post.Id);
if (newsPost == null) return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
newsPost.Title = post.Title;
newsPost.Summary = post.Summary;
newsPost.Content = post.Content;
db.Entry(newsPost).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
return View(post);
这样做的最佳实践方法是什么?
谢谢!
【问题讨论】:
我相信使用像 AutoMapper 这样的东西可能是一种方法。 使用 EF6,您应该能够在保存之前使用db.Entry(post).State = EntityState.Modified;
,后跟db.Entry(post).Property(x => x.Created).IsModified = false;
我会看看 ViewModel 模式 (geekswithblogs.net/michelotti/archive/2009/10/25/…)。编写视图模型,将其发送到您的 HttpGet 方法,发回 HttpPost 方法,验证,更新您的实体模型。正如 Kamo 所指出的,Automapper 非常适合这一点。然后你可以在你不想更新的字段上使用 html.HiddenFor。
@SteveGreene,感谢您的评论。对于我不想修改的字段,我想避免使用 Html.HiddenFor,因为通过代理或浏览器插件等更改这些字段是微不足道的。
View Models 解决这个问题,这样你就不必传递隐藏字段了。
【参考方案1】:
EF 还有一个简单的内置“AutoMapper”,可以处理标量值。
public class PostViewModel()
public string Id get;set;
public string Title get;set;
public string Summary get;set;
public string Content get;set;
public ActionResult Edit(PostViewModel viewModel)
if (ModelState.IsValid)
var newsPost = db.Posts.Find(post.Id);
...
db.Entry(newsPost).CurrentValues.SetValues(viewModel);
...
【讨论】:
这真的是唯一的方法吗...对数据库的额外调用让我畏缩... 但是,这很简单。太好了。【参考方案2】:我使用存储库方法。效果很好。 它复制不同的列。针对 PUT 的 PATCH 排序
public void CopyUpdate<T> (T modelorig, T model) where T : class
_context.Entry(model).CurrentValues.SetValues(modelorig);
_context.Set<T>().Add(model);
_context.Entry(model).State = EntityState.Modified;
_context.SaveChanges();
【讨论】:
【参考方案3】:假设你想坚持休息,这样做的“正确”方法。是用HttpPatch
。
https://docs.microsoft.com/en-us/aspnet/core/web-api/jsonpatch?view=aspnetcore-6.0
[HttpPatch]
[ValidateAntiForgeryToken]
public async Task<ActionResult> PatchAsync([FromBody] JsonPatchDocument<Post> patchDoc, int id)
var post = db.Find(id);
patchDoc.ApplyTo(post, ModelState);
if (!ModelState.IsValid)
return BadRequest(ModelState);
await db.SaveChangesAsync();
return new ObjectResult(post);
【讨论】:
以上是关于在 MVC 中仅更新对象的某些字段的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Entity Framework 6.1 中仅加载子对象的某些字段?
如何在 Java 中仅更新 @Transactional 方法中更改的字段?