Я использую 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() следующим образом:
@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>
}
Это даст мне исключение ссылочной ссылки, даже если я использую новое ключевое слово:
System.NullReferenceException: Object reference not set to an instance of an object.
Почему это происходит? Может ли кто-нибудь помочь?
спасибо
Ваша подпись действия должна быть:
public ActionResult CreateComment(Comment model)
Имена, сгенерированные для полей формы, будут привязаны к свойствам одного и того же класса модели. Там нет способа для рамки, чтобы знать, например, что CommenterName
свойство должно совпадать с name
параметра действия.
Второй пример имеет мало смысла - вы пытаетесь записать идентификатор, но никогда не задавали его. Фактически, вы даже не пропускаете 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
в своем действии с помощью:
[HttpPost]
public ActionResult CreateComment(CommentViewModel model)
{
var comment = new Comment();
comment.CommenterName = model.Name;
// etc...
}
Это не позволяет пользователю устанавливать такие вещи, как Approved
and CreatedDate
.