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),同样的日期也会被提交。但我敢打赌,除了在源代码中将其作为隐藏字段之外,还有其他方法吗?我的意思是,在另一个例子中,这不是很安全吗?所以我想要的不是隐藏的领域。你们能帮我吗?

如果我尝试按原样运行。我会收到一个错误,那就是我的日期没有设置,这是合乎逻辑的,因为它也想更新那个日期。但我不想。如果你能这么说的话,我想让它随意选择。

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

不要从陌生人那里拿走糖果

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

[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方法添加自定义验证规则,在域层强制执行这样的规则。

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

您需要将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();

但是,如果你只是在做一些领域,那么上面的内容是有意义的。用你的脑袋!