由于我正在学习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)
并提交相同的日期。但我敢打赌除了将它作为源代码中的隐藏字段之外还有另一种方式吗?我的意思是在另一个例子中这不安全吗?所以我想要隐藏的字段而不是其他东西。你能帮助我吗?
如果我尝试按原样运行它。我收到的错误是我的日期没有设置,这是逻辑,因为它想要更新那个。但我不想要它。如果可以的话,我想让它保持可选。
答案 0 :(得分: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
方法添加自定义验证规则,在域层强制执行此类规则。
答案 1 :(得分:0)
DateTime是值类型,不能为null。因此,它永远不会是可选的。
你需要使它成为可以为空的类型。即
public DateTime? Date {get;set;}
通常,ViewModel中的大多数值类型都应该是可空的,然后使用Required属性强制它们包含值。这允许您判断它们是否输入了值,或者它是否是默认值。
在您的控制器中,您可以检查日期是否具有Date.HasValue
的值,如果是,则保存日期。
关于安全性,在这种情况下,它不是一个问题。假设某人有权访问该页面(他们通过了授权)并且他们有权更新日期,那么用户是否可以绕过它并不重要。他们所能做的就是提交有效的日期格式。除非您想添加逻辑以确保日期在特定时间段内,否则您不必担心。 ModelBinder不会绑定到无效的日期格式。
如果您想控制用户是否可以更新日期,比如基于角色,那么您可以向控制器添加逻辑以检查日期是否有值且用户是否处于正确的角色,否则会发出错误
<强>更新强>
我认为这里最简单的解决方案是做两件事。第一个是使Date可以为空,如上所述。虽然如果您在视图中没有Date的表单字段,但这并不是绝对必要的,如果您稍后要添加表单字段,那么如果您将文本框留空,则会出现验证错误。我希望尽可能防止将来发生错误。此外,如果某人手动将值发布到您的“编辑”操作,并且它们包含空白日期字段,则无法验证,而不是简单地忽略它。使值为nullable允许完全忽略该值,无论其值如何。
其次,@ p.s.w.g建议做什么,只更新你想要更新的字段。从数据库中检索帖子,然后更新除Id和Date之外的所有字段。然后拨打SaveChanges()
。
答案 2 :(得分:0)
这里只是我的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!