ASP.NET MVC:编辑时忽略字段
本文关键字:字段 编辑 NET MVC ASP | 更新日期: 2023-09-27 18:05:30
在学习ASP.NET MVC的过程中,我遇到了一个问题和一些麻烦
我正在尝试创建一个简单的博客,只是为了测试我到目前为止所学到的东西。但当涉及到编辑和离开一个领域时,我遇到了一个问题。
我正在尝试编辑我博客上已经提交的帖子,该帖子包含几个字段:Id、标题、消息、作者和提交日期,这些字段不应编辑,保持原样。
这里有一些代码:
我的帖子模型:
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";
}
<h2>Rediger "@Model.Headline"</h2>
@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)
<input type="submit" value="Gem" />
}
我知道我可以投一个@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<Post>();
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
方法添加自定义验证规则,在域层强制执行这样的规则。
您需要将it设置为可为null的类型。即
public DateTime? Date {get;set;}
通常,ViewModel中的大多数值类型都应该可以为null,然后使用Required属性强制它们包含值。这允许您判断他们是否未能输入值,或者该值是否为默认值。
然后,在控制器中,您可以检查Date是否具有Date.HasValue
值,如果是,则保存日期。
关于安全,在这种情况下,这不是一个真正的问题。假设有人可以访问该页面(他们通过授权(,并且有权更新日期,那么用户是否可以绕过它也没关系。他们所能做的就是提交一个有效的日期格式。除非你想添加逻辑以确保日期在特定的时间段内,否则你不必担心。ModelBinder不会绑定到无效的日期格式。
如果你想控制用户是否可以更新日期,比如说根据角色,那么你可以向控制器添加逻辑,检查日期是否有值,用户是否处于正确的角色,否则会发出错误。
更新:
我认为这里最简单的解决方案是做两件事。第一个是使Date可以为null,正如我上面提到的。尽管如果您的视图中没有日期的表单字段,这不是绝对必要的,但如果稍后添加表单字段,如果将文本框留空,则会出现验证错误。如果可能的话,我喜欢防止将来发生错误。此外,如果有人手动将值发布到您的"编辑"操作中,并且其中包含一个空的"日期"字段,则该操作将无法验证,而不是简单地忽略它。将该值设为null可以使该值完全被忽略,而不管其值如何。
第二,按照@p.s.w.g的建议,只更新您想要更新的字段。从数据库中检索帖子,然后更新除Id和Date之外的所有字段。然后呼叫SaveChanges()
。
这里只有我的2个元素。我知道这是一个简单的情况,给出的答案很好很直接。但随着属性列表的增长,这可能会变得困难。
因此,一种不同的方法是沿着
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();
但是,如果你只是在做一些领域,那么上面的内容是有意义的。用你的脑袋!