a bit of a strange one here. I’ve got a blog that’s another ‘dip my toe into MVC’ project that will highlight the benefits of our new Intranet. I have a typical blog post page with the article, comments and a form to submit your comments against a given article.
I have a stringly typed main View (“Post”) which has the article content, then two Html.RenderAction methods; one to get the comments and one to add comments via a form.
My issue is that when a comment is posted, my GetComments method is called before AddComment, so when the page is refreshed the new comment isn’t visible although it has been added to the database. A quick F5 confirms this. I understand that GetComments is being called first due to it being declared first in the view but I’m not sure how to tell the view to do an add before a get.
Here’s my code:
Controller:
public ActionResult AddComment()
{
return PartialView("AddComment");
}
[HttpPost]
public ActionResult AddComment(Comment comment)
{
comment.DateSubmitted = DateTime.Now;
db.Comments.Add(comment);
db.SaveChanges();
return PartialView(comment);
}
public ActionResult GetComments(int articleid)
{
var comments = db.Comments.Where(c => c.ArticleID == articleid).ToList();
return PartialView(comments);
}
Post view
@model IntranetBlog.Models.Article
@{
ViewBag.Title = "Post";
}
<div class="row">
<div class="span12">
<h3>@Html.DisplayFor(modelItem => Model.Title)</h3>
<small>by Ruth Barlow on @Html.DisplayFor(modelItem => Model.DateCreated)</small>
@if (Model.Image != null)
{
<p>
<img src="@Url.Action("GetImage", "Home", new { articleID = Model.ArticleID })" alt="" width="150" height="150" />
</p>
}
<div>
@Html.DisplayFor(modelItem => Model.Body)
</div>
<small>Posted under @Html.DisplayFor(modelItem => Model.Category.Name)</small>
</div>
<div class="span12">
@{
Html.RenderAction("GetComments", "Home", new { articleID = Model.ArticleID });
}
</div>
<div class="span12">
@{
Html.RenderAction("AddComment", "Home", new { articleID = Model.ArticleID });
}
</div>
</div>
GetComments partial:
@model IEnumerable<IntranetBlog.Models.Comment>
@if (Model.Any())
{
<h3>What you're saying</h3>
foreach (var item in Model)
{
<div>
Comment: @Html.DisplayFor(modelItem => item.Body)
</div>
<div>
Submitted by: @Html.DisplayFor(modelItem => item.SubmittedBy)
on @Html.DisplayFor(modelItem => item.DateSubmitted)
</div>
<hr />
}
}
else
{
<p>There are no comments for this post. Why not add one?</p>
}
AddComment partial
@model IntranetBlog.Models.Comment
@using (Html.BeginForm())
{
<h3>Why not leave us a comment?</h3>
@Html.ValidationSummary()
<fieldset>
<div class="editor-label">
@Html.LabelFor(model => model.Body)
</div>
<div class="editor-field">
@Html.TextAreaFor(model => model.Body, 20, 20, null)
@Html.ValidationMessageFor(model => model.Body)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.SubmittedBy)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.SubmittedBy)
@Html.ValidationMessageFor(model => model.SubmittedBy)
</div>
<p>
<input type="submit" value="Add comment" id="AddComment" class="btn btn- primary" />
</p>
</fieldset>
}
Hope this makes sense.
Thanks in advance.
The trick is to use
Html.Actioninstead ofHtml.RenderActionthis will allow you to store the result in a variable and then add it to the display where it is needed.This will allow you to generate the PartialView in the logical order you need, while displaying them in an other order.
See this post for a quick example on how to do it : https://stackoverflow.com/a/13301057/971693