4

在学习 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)并且将提交相同的日期。但我敢打赌,除了将其作为源代码中的隐藏字段之外,还有另一种方法吗?我的意思是在另一个例子中这不是那么安全吗?所以我想要这里的隐藏字段以外的东西。你们能帮帮我吗?

如果我尝试按原样运行它。我收到一个错误,即我的日期未设置,这是合乎逻辑的,因为它也想更新该日期。但我不希望它。如果你能这么说,我想把它留作可选。

4

3 回答 3

8

不要从陌生人那里拿糖果

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

[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

于 2013-03-24T19:51:10.923 回答
0

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

您需要将它设为可为空的类型。IE。

public DateTime? Date {get;set;}

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

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

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

如果您想控制用户是否可以更新日期,比如基于角色,那么您可以向控制器添加逻辑以检查日期是否有值并且用户是否处于正确的角色,否则会发出错误。

更新:

我认为这里最简单的解决方案是做两件事。第一个是使 Date 可以为空,正如我上面提到的。尽管如果您的视图中没有 Date 的表单域,这并不是绝对必要的,但如果您稍后添加表单域,那么如果您将文本框留空,则会收到验证错误。如果可能的话,我喜欢防止将来发生错误。此外,如果有人手动将值发布到您的编辑操作,并且它们包含一个空白日期字段,它将无法验证,而不是简单地忽略它。使值可为空允许该值被完全忽略,而不管其值如何。

其次,按照@pswg 的建议进行操作,并且只更新您想要更新的字段。从数据库中检索帖子,然后更新除 Id 和 Date 之外的所有字段。然后调用SaveChanges()

于 2013-03-24T20:00:07.977 回答
0

这里只有我的 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();

但是,如果您只是在做一些领域,那么上述内容是有道理的。就用你的脑袋!

于 2016-06-23T11:12:24.307 回答