ASP.NET MVC:编辑时忽略字段

由于我正在学习ASP.NET MVC,我遇到了一个问题并遇到了一些麻烦

我正在尝试创建一个简单的博客,只是为了测试我到目前为止学到的东西。 但是当谈到编辑和离开一个领域我遇到了问题。

我正在尝试在我的博客上编辑已提交的post,该post包含几个字段:提交的标题,标题,消息,作者和日期,不应该被编辑,只是保持原样。

这是一些代码:

我的post模型:

namespace MyBlock.Models { public class Post { public int Id { get; set; } [Required] public string Author { get; set; } [Required] public string Headline { get; set; } [Required] public string Message { get; set; } public DateTime Date { get; set; } } } 

我的编辑:

 [HttpGet] public ActionResult Edit(int id = 0) { Post post = db.Posts.Find(id); if (post != null) { return View(post); } return HttpNotFound(); } [HttpPost] public ActionResult Edit(Post post) { if (ModelState.IsValid) { db.Entry(post).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index", "Home"); } return View(post); } 

我的编辑观点:

 @model MyBlock.Models.Post @{ ViewBag.Title = "Edit"; } 

Rediger "@Model.Headline"

@using (Html.BeginForm()) { @Html.LabelFor(u => u.Author) @Html.TextBoxFor(u => u.Author) @Html.LabelFor(u => u.Headline) @Html.TextBoxFor(u => u.Headline) @Html.LabelFor(u => u.Message) @Html.TextAreaFor(u => u.Message) }

我知道我可以投入@HiddenFor(u => u.Date)并提交相同的日期。 但我敢打赌除了将它作为源代码中的隐藏字段之外还有另一种方式吗? 我的意思是在另一个例子中这不安全吗? 所以我想要其他东西而不是隐藏的领域。 你们能帮助我吗?

如果我尝试按原样运行它。 我收到一个错误,这是我的日期没有设置,这是逻辑,因为它想要更新那个。 但我不想要它。 如果你能说的话,我想把它留给我们。

不要从陌生人那里拿糖果

换句话说,不要从客户端获取信息并直接更新数据库。 您应该在服务器端强制执行业务规则,而不是信任客户端为您执行此操作。

 [HttpPost] public ActionResult Edit(Post post) { if (ModelState.IsValid) { var dbPost = db.Posts.FirstOrDefault(p => p.Id == post.Id); if (dbPost == null) { return HttpNotFound(); } dbPost.Author = post.Author; dbPost.Message = post.Message; dbPost.Headline = post.Headline; db.SaveChanges(); return RedirectToAction("Index", "Home"); } return View(post); } [HttpPost] public ActionResult Add(Post post) { if (ModelState.IsValid) { var dbPost = db.Create(); dbPost.Author = post.Author; dbPost.Message = post.Message; dbPost.Headline = post.Headline; dbPost.Date = DateTime.Now(); // Don't trust client to send current date db.SaveChanges(); return RedirectToAction("Index", "Home"); } return View(post); } 

在我自己的项目中,我通过向ValidateEntity方法添加自定义validation规则在域层强制执行此类规则。

DateTime是值类型,不能为null。 因此,它永远不会是可选的。

你需要使它成为可以为空的类型。 即。

 public DateTime? Date {get;set;} 

通常,ViewModel中的大多数值类型都应该是可空的,然后使用Required属性强制它们包含值。 这允许您判断它们是否输入了值,或者它是否为默认值。

在控制器中,您可以检查Date是否具有Date.HasValue值,如果是,则保存日期。

关于安全性,在这种情况下,它不是一个问题。 假设某人有权访问该页面(他们通过授权)并且他们有权更新日期,那么用户是否可以绕过它并不重要。 他们所能做的就是提交有效的日期格式。 除非您想添加逻辑以确保日期在特定时间段内,否则您不必担心。 ModelBinder不会绑定到无效的日期格式。

如果要控制用户是否可以更新日期(例如基于角色),则可以向控制器添加逻辑以检查日期是否具有值且用户是否具有正确的角色,否则会发出错误。

更新:

我认为这里最简单的解决方案是做两件事。 第一个是使Date可以为空,如上所述。 虽然如果您在视图中没有Date的表单字段,但这并不是绝对必要的,如果您稍后要添加表单字段,那么如果您将文本框留空,则会出现validation错误。 我希望尽可能防止将来发生错误。 此外,如果有人手动将值发布到您的“编辑”操作,并且它们包含空白日期字段,则无法validation,而不是简单地忽略它。 使值可为空可以使值完全被忽略,无论其值如何。

其次,是@pswg建议做什么,只更新你想要更新的字段。 从数据库中检索post,然后更新除Id和Date之外的所有字段。 然后调用SaveChanges()

这是我的2点。 我知道这是一个简单的情况,给出的答案很简单明了。 但随着属性列表的增长,它可能会变得困难。

因此,沿着这些方向不同的approuch

  var t = _db.Blog.Where(x => x.ID == id).FirstOrDefault(); var info = typeof(Blog).GetProperties(); //properties you don't want to update var properties = info.Where(x => x.Name != "xxx" && x.Name != "xxxx").ToList(); foreach(var p in properties) { p.SetValue(t, p.GetValue(temp.Volunteer)); } _db.Entry(t).State = EntityState.Modified; _db.SaveChanges(); 

但是,如果你只是在做几个领域,那么上述意义重大。 只需使用你的noggin!