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

C# ASP.NET MVC:编辑时忽略字段,c#,asp.net,.net,asp.net-mvc,asp.net-mvc-3,C#,Asp.net,.net,Asp.net Mvc,Asp.net Mvc 3,在学习ASP.NETMVC的过程中,我遇到了一个问题和一些麻烦 我正在尝试创建一个简单的博客,只是为了测试我迄今为止所学到的东西。但当涉及到编辑和离开字段时,我遇到了一个问题 我试图在我的博客上编辑一篇已经提交的文章,这篇文章包含几个字段:Id、标题、消息、作者和提交日期,不应该编辑,只保留原样 下面是一些代码: 我的帖子模型: namespace MyBlock.Models { public class Post { public int Id { get;

在学习ASP.NETMVC的过程中,我遇到了一个问题和一些麻烦

我正在尝试创建一个简单的博客,只是为了测试我迄今为止所学到的东西。但当涉及到编辑和离开字段时,我遇到了一个问题

我试图在我的博客上编辑一篇已经提交的文章,这篇文章包含几个字段: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" />
}
@model MyBlock.Models.Post
@{
ViewBag.Title=“编辑”;
}
Rediger“@Model.Headline”
@使用(Html.BeginForm()){
@LabelFor(u=>u.Author)
@Html.TextBoxFor(u=>u.Author)
@LabelFor(u=>u.Headline)
@Html.TextBoxFor(u=>u.Headline)
@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<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);
}
[HttpPost]
公共行动结果编辑(发布)
{
if(ModelState.IsValid){
var dbPost=db.Posts.FirstOrDefault(p=>p.Id==post.Id);
if(dbPost==null)
{
返回HttpNotFound();
}
dbPost.Author=post.Author;
dbPost.Message=post.Message;
dbPost.Headline=post.Headline;
db.SaveChanges();
返回重定向到操作(“索引”、“主页”);
}
返回视图(post);
}
[HttpPost]
公共行动结果添加(发布)
{
if(ModelState.IsValid){
var dbPost=db.Create();
dbPost.Author=post.Author;
dbPost.Message=post.Message;
dbPost.Headline=post.Headline;
dbPost.Date=DateTime.Now();//不信任客户端发送当前日期
db.SaveChanges();
返回重定向到操作(“索引”、“主页”);
}
返回视图(post);
}

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

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

您需要将其设置为可为null的类型。即

public DateTime? Date {get;set;}
通常,ViewModel中的大多数值类型都应该是可空的,然后使用必需的属性强制它们包含值。这允许您判断他们是否未能输入值,或者该值是否为默认值

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

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

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

更新:

我认为最简单的解决办法是做两件事。第一个是使日期为空,正如我上面提到的。虽然如果视图中没有日期的表单字段,则严格来说这不是必需的,但是如果以后要添加表单字段,则如果文本框为空,则会出现验证错误。如果可能的话,我喜欢防止将来发生错误。此外,如果有人手动将值发布到您的编辑操作中,并且这些值包含一个空白的日期字段,则该字段将无法验证,而不是简单地忽略它。使该值可为null允许完全忽略该值,而不考虑其值


第二,按照@p.s.w.g的建议去做,只更新你想要更新的字段。从数据库中检索帖子,然后更新除Id和日期之外的所有字段。然后调用
SaveChanges()。我知道这是一个简单的情况,给出的答案是好的和直接的。但随着属性列表的增长,这可能会变得困难

因此,不同的方法是沿着这些路线

    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();
但是如果你只是在做一些领域的工作,那么上面的内容是有意义的。
用你的酒

这与提交相同吗?我的意思是创建/写入数据到数据库?这很好。我确实有一个关于“向数据库写入”的问题,我该怎么做?如何检索用户在视图中写入的内容?如果我不拿糖果:)现在我在我的写操作结果中有这个:
If(ModelState.IsValid){post.Date=DateTime.now;db.Posts.Add(post);db.SaveChanges();return RedirectToAction(“Index”,“Home”);}
@kasperhydalpedersen一切都在等着你。
db.Posts.FirstOrDefault(…)
行查询数据库以查找帖子的当前状态,然后验证帖子是否确实存在。接下来的几行准备更新帖子,从action参数获取用户输入。最后,
db.SaveChanges()
将这些更改提交到数据库。@Kas