我正在使用MVC来构建博客。我想要的是将帖子评论保存到数据库中的相应位置,但它不起作用。
我的帖子模型如下:
public class Post
{
[Key]
public int PostId { get; set; }
public string Title { get; set; }
public DateTime CreatedDate{get;set;}
public DateTime UpdateDate { get; set; }
public string Body { get; set; }
public ICollection<Comment> Comments { get; set;}
public ICollection<Tag> Tags { get; set; }
}
我的评论模型如下:
public class Comment
{
[Key]
public int CommentId { get; set; }
public int PostId { get; set; }
[ForeignKey("PostId")]
public virtual Post Post{get; set;}
public string CommentCreateDate { get; set; }
public string CommentUpdateDate { get; set; }
public string CommeterName { get; set; }
public string EmailAddress { get; set; }
public string CommentText { get; set; }
public bool Approved { get; set; }
}
我有以下行动方法:
[HttpGet]
public ActionResult CreateComment()
{
return View();
}
[HttpPost]
[ValidateInput(false)]
public ActionResult CreateComment(int id, string name, string email, string txt, bool aproved = false)
{
Post post = GetPost(id);
Comment comment = new Comment();
comment.Post = post;
comment.CommentCreateDate = DateTime.Now.ToString();
comment.CommeterName = name;
comment.EmailAddress = email;
comment.CommentText = txt;
comment.Approved = aproved;
db.Comments.Add(comment);
db.SaveChanges();
m_commentList.Add(comment);
return RedirectToAction("CreateComment", new { id = id });
}
在我看来,我正在尝试这个:
@model Blog.Models.Comment
@{
ViewBag.Title = "CreateComment";
}
<h2>Create a Comment</h2>
@using (Html.BeginForm())
{
<fieldset>
<legend>Enter Comment</legend>
<div class="editor-label">
@Html.LabelFor(model => model.CommeterName)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.CommeterName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.EmailAddress)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.EmailAddress)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.CommentText)
</div>
<div class="editor-field">
@Html.TextAreaFor(model => model.CommentText)
</div>
<p>
<input type="submit" value="Create comment" />
</p>
</fieldset>
}
我没有例外,但没有保存表单中的数据。仅限操作结果中设置的数据,即CommentCreateDate和Approved。我不确定我做错了什么。
我尝试了第二个选项,即在BeginForm()中包含注释的id,如下所示:
@using (Html.BeginForm(new {id = Model.CommentId}))
{
<fieldset>
<legend>Enter Comment</legend>
<div class="editor-label">
@Html.LabelFor(model => model.CommeterName)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.CommeterName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.EmailAddress)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.EmailAddress)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.CommentText)
</div>
<div class="editor-field">
@Html.TextAreaFor(model => model.CommentText)
</div>
<p>
<input type="submit" value="Create comment" />
</p>
</fieldset>
}
即使我使用new关键字,这也会给我一个空引用异常:
System.NullReferenceException: Object reference not set to an instance of an object.
为什么会这样?有人可以帮忙吗?
谢谢
答案 0 :(得分:2)
您的行动签名应为:
public ActionResult CreateComment(Comment model)
为表单字段生成的名称将绑定回相同模型类的属性。例如,框架无法知道CommenterName
属性应该与操作的name
参数匹配。
你的第二个例子没什么意义 - 你试图写出ID,但你从未设置过。实际上,您甚至没有将Comment
传递给带有表单的视图,这就是您获得NullReferenceException
的原因:
[HttpGet]
public ActionResult CreateComment()
{
return View();
}
此外,您应该注意您向模型和操作公开的字段。例如,用户可以通过浏览器的开发控制台添加以下标记,轻松强制批准他们的评论:
<input type="hidden" name="approved" value="true" />
用户可以设置模型属性中的任何内容或操作的参数。
一个更好的选择是为表单使用专用的模型类:
public class CreateCommentViewModel
{
public string Name { get; set; }
public string Email { get; set; }
public string Text { get; set; }
}
然后使用以下内容将此映射到您的Comment
{/ p>
[HttpPost]
public ActionResult CreateComment(CommentViewModel model)
{
var comment = new Comment();
comment.CommenterName = model.Name;
// etc...
}
这可以防止用户设置Approved
和CreatedDate
之类的内容。