Answered by:
Blog Page with Comments in PartialView

Question
-
User-1641868886 posted
I am trying to learn a simple Blog format piecing together some examples. I have a "Blog" model and a "Comments" model. On my view, I have a "@foreach" to produce a list of the blog posts. I am trying to include a Comments element inside the Blog list. Here is my view:
@foreach (var item in Model) { @Html.HiddenFor(modelItem => item.BlogId) <div> <span class="blogtitle">@Html.DisplayFor(modelItem => item.Title)</span> <span class="blogdate padding">@Html.DisplayFor(modelItem => item.Date)</span> </div> <div class="blogauthor"> <span><a src="#">@Html.DisplayFor(modelItem => item.Author)</a></span> </div> <div class="blogbody"> <span>@Html.DisplayFor(modelItem => item.Content)</span> </div> <div class="blogcomments" id="CommentsDiv"> <span>@Html.TextAreaFor(modelItem => item.Comment, new { style="width:60%; margin-right:10px" })</span><input id="CommSubmit" type="submit" value="Post" class="btn btn-xs btn-default" /> </div> <div class="showComments"> ***somewhere in this tag I need to pass the "BlogId" to the partialView controller action*** @Html.Partial("_ShowComments", new List<Docx_Site_Web.Models.Comments>() { new Docx_Site_Web.Models.Comments() }) </div>
}In declaring the "_ShowComments" partial, I do not get any error, the page loads but does not show any comments. I am obviously not passing in the associated "BlogId" for the "_ShowComments" list in the partial. I am not sure how to pass that variable in this example, or if I am constructing this correctly. I have a jQuery to handle the comments textbox and submit button but I've not gotten to that yet. At this point, I'm just trying to show comments associated with each BlogId item.
Should I be using "@Html.Action" or "@Html.RenderAction" instead of "Partial"?
Thanks for looking and any suggestions.
RC
Sunday, July 21, 2019 7:13 PM
Answers
-
User1520731567 posted
Hi ReidMelSam,
public List<Comments> Comments { get; set; }
public ICollection<Blog> Blog { get; set; }
As I can see in your model,I confused that your Blog and Comments is many to many entity,
I am very surprised: a blog can have multiple comments, but why one comment belongs to multiple blogs?
return PartialView(DataAccess.ReturnList<Comments>("spBlogs_GetCommentsByBlogId", param).ToList<Comments>());
So,I suggest you could check if the highlight part complies with the complex entity.
Best Regards.
Yuki Tao
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Tuesday, July 23, 2019 9:01 AM
All replies
-
User-821857111 posted
You should instantiate the Comments collection as part of the model, then pass that to the partial:
Action Method:
var model = new ViewModel{
...
Comments = context.Getcomments() // or whatever way you get the comments
};
return View(model);
then in your View:
@Html.Partial("_ShowComments", model.Comments)
Monday, July 22, 2019 6:36 AM -
User1520731567 posted
Hi ReidMelSam,
Should I be using "@Html.Action" or "@Html.RenderAction" instead of "Partial"?
@Html.Action,@Html.RenderAction:
you need to call an action,here maybe will execute some logic,finally return partial view.
The main difference is that @Html.RenderAction renders result directly to response that’s why it is more efficient if the action returns a large amount of HTML over @Html.Action.
@Html.Partial:
It call partial view directly.
So you need to know if you need to call a partial view via action,
If your business logic is simple, you can call a partial view by @Html.Partial.
@Html.Partial("_ShowComments", new List<Docx_Site_Web.Models.Comments>() { new Docx_Site_Web.Models.Comments() })
I need to know how is model do you call in _ShowComments partial view:
for example:
Blog and comments is one to many entity:
so the model is like:
public class Blog { public int BlogId{ get; set; } public string Title{ get; set; } ... public virtual ICollection<Comment> Comments{ get; set; } }
public class Comment { public int CommentId{ get; set; } public string Title{ get; set; } ... public virtual Blog Blog{ get; set; }
}in View:(this view should like Edit or Details view,it already call model by specified id )
public ActionResult Details(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Blog blog = db.Blog.Find(id); if (blog == null) { return HttpNotFound(); } return View(blog); }
@model xxxx.Models.Blog
....
<div class="showComments"> ***somewhere in this tag I need to pass the "BlogId" to the partialView controller action*** @Html.Partial("_ShowComments", Model.Comments}) </div> }in _ShowComments partial view:
@model List<xxx.Models.Comment> @{ foreach (var item in Model) { <input type="text" value="@item.Title"/> } }
You could refer to this article about one to many entity:
If you still have any questions,please post your model and view.
Best Regards.
Yuki Tao
Monday, July 22, 2019 9:45 AM -
User-1641868886 posted
Thanks for the suggestions. Here is what I have at this point. But first, two points that MAY matter, or not:
1) I am using Dapper ORM data access. I am frequently told "it doesn't matter" but controller and in some cases view c# have slightly different syntax and my problem is I am not yet good enough to see examples in EF, then write what I need for Dapper. So I am including the controller action. It is NOT picking up any "BlogId" parameter. For an "IEnumberable List" it seems like the controller should pick up several BlogIds.
2) The "_ShowComments" action is being called inside a "@foreach" IEnumerable list of blogs, rather than from a single blog post. I may not yet fully understand how this needs to work. First is the "_ShowComments" controller action:
[HttpGet] public ActionResult _ShowComments(int id) { DynamicParameters param = new DynamicParameters(); param.Add("@BlogId", id); return PartialView(DataAccess.ReturnList<Comments>("spBlogs_GetCommentsByBlogId", param).ToList<Comments>()); }
Next are the two models, "Blog" and "Comments":
public class Blog { [Key] public int BlogId { get; set; } [Required] [Display(Name = "Blog Title")] public string Title { get; set; } [Required] [Display(Name = "Author")] public string Author { get; set; } [Required] [Display(Name = "Content")] [DataType(DataType.MultilineText)] public string Content { get; set; } [Display(Name = "User Name")] public string UserName { get; set; } [Display(Name = "Comments")] [DataType(DataType.MultilineText)] public string Comment { get; set; } [DataType(DataType.DateTime)] [DisplayFormat(DataFormatString = "{0:g}")] public DateTime Date { get; set; } public int Comm_Id { get; set; } public List<Comments> Comments { get; set; } } public class Comments { [Key] public int Comm_Id { get; set; } public int BlogId { get; set; } public string UserName { get; set; } [Required] public string Comment { get; set; } [DataType(DataType.DateTime)] [DisplayFormat(DataFormatString = "{0:g}")] public DateTime Date { get; set; } public ICollection<Blog> Blog { get; set; } }
Now the current call for the action "_ShowComments" inside the "@foreach" list of blogs:
@foreach (var item in Model) { @Html.HiddenFor(modelItem => item.BlogId) @Html.HiddenFor(modelItem => item.UserName) <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"> <div> <span class="blogtitle">@Html.DisplayFor(modelItem => item.Title)</span><span class="blogdate padding">@Html.DisplayFor(modelItem => item.Date)</span> </div> <div class="blogauthor"> <span><a src="#">@Html.DisplayFor(modelItem => item.Author)</a></span> </div> <div class="blogbody"> <span>@Html.DisplayFor(modelItem => item.Content)</span> </div> <div class="postcomments"> @Html.Action("_ShowComments", "Blog", new { BlogId = item.BlogId }) </div> </div> }
...and finally, the partial view that is being called:
@if(Model != null) { foreach (var BlogId in Model) { var item = new Docx_Site_Web.Models.Comments(); @Html.HiddenFor(modelItem => item.Comm_Id) @*@Html.HiddenFor(modelItem => item.BlogId)*@ <div class="usertag"> <span>@Html.DisplayFor(ModelItem => item.UserName)</span><span class="float-right">@Html.DisplayFor(ModelItem => item.Date)</span> </div> <div class="blogcomments"> @Html.DisplayFor(modelItem => item.Comment) </div> } }
For this current version, the code runs, no error, but no comments appear for any of the blog items. I have tried to debug the controller, when it hits the "return PartialView" line, the parameter is empty where I expect to see an array of BlogIds sent to the controller.
Thanks again for any suggestions how to fix.
RC
Monday, July 22, 2019 9:30 PM -
User1520731567 posted
Hi ReidMelSam,
public ActionResult _ShowComments(int id)
@Html.Action("_ShowComments", "Blog", new { BlogId = item.BlogId })
According to your code,I find your parameter are inconsistent between @Html.Action and action.You could modify action like:
public ActionResult _ShowComments(int BlogId)
public ActionResult _ShowComments(int id) { DynamicParameters param = new DynamicParameters(); param.Add("@BlogId", id); return PartialView(DataAccess.ReturnList<Comments>("spBlogs_GetCommentsByBlogId", param).ToList<Comments>()); }
According to your action code,you finally return List<Comments> model,so your _ShowComments partial view should receive this strong type model,like:
@model List<xxx.xxx.xxx.Comments>
Best Regards.
Yuki Tao
Tuesday, July 23, 2019 2:32 AM -
User-1641868886 posted
Thanks for further suggestions. A little progress. Now I get a return of parameters (BlogId 1,2,3 etc.) as I loop through debugging of the controller Action. I did make the change you suggested by making the "BlogId" consistent in the controller Action and the "@Html.Action".
I am seeing a partial view on Blog items where one is supposed to appear (BlogId # 3 has comments, but BlogId #1 & #2 don't) and not where there is no comment. But all I see is an empty PartialView with no data. My storedproc returns what I want when I run it, but the controller Action is not sending any data to the "_ShowComments" partial View.
So...the controller action IS working as far as sending BlogIds to the View that have comments...but not sending the data in the rows.
Let me know if you see anything else wrong with the controller Action:
[HttpGet] public ActionResult _ShowComments(int BlogId) { DynamicParameters param = new DynamicParameters(); param.Add("@BlogId", BlogId); return PartialView(DataAccess.ReturnList<Comments>("spBlogs_GetCommentsByBlogId", param).ToList<Comments>()); }
Thanks again!
RC
Tuesday, July 23, 2019 4:45 AM -
User1520731567 posted
Hi ReidMelSam,
public List<Comments> Comments { get; set; }
public ICollection<Blog> Blog { get; set; }
As I can see in your model,I confused that your Blog and Comments is many to many entity,
I am very surprised: a blog can have multiple comments, but why one comment belongs to multiple blogs?
return PartialView(DataAccess.ReturnList<Comments>("spBlogs_GetCommentsByBlogId", param).ToList<Comments>());
So,I suggest you could check if the highlight part complies with the complex entity.
Best Regards.
Yuki Tao
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Tuesday, July 23, 2019 9:01 AM -
User-1641868886 posted
Since this is not Entity Framework, I built these models from scratch. Since I am still learning, I sometimes either duplicate efforts, or create an element that points in the opposite direction.
If I am correct, you're saying that the second one,
public ICollection<Blog> Blog { get; set; }
runs in the wrong direction, making it look like I am assigning a comment to multiple Blog instances? If so, I will delete that declaration but keep the other one,
public List<Comments> Comments { get; set; }
which is in the "Blog" model. Thanks. I think that will help stop any confusion, but I am still looking at what I need to do for my empty string of comments. Last night I asked about the controller Action, but now I am thinking it may be a problem with how I am instantiating the list item(s) on the view:
@if (Model != null) { foreach (var BlogId in Model) { var item = new Docx_Site_Web.Models.Comments(); <div class="panel panel-primary"> @Html.HiddenFor(modelItem => item.Comm_Id) @*@Html.HiddenFor(modelItem => item.BlogId)*@ <div class="usertag"> <span>@Html.DisplayFor(ModelItem => item.UserName)</span><span class="float-right">@Html.DisplayFor(ModelItem => item.Date)</span> </div> <div class="blogcomments"> <p>@Html.DisplayFor(modelItem => item.Comment)comments placeholder</p> </div> </div> } }
Update: I needed to reverse the two statements at the top of the partialView, and revise as follows:
@foreach (var item in Model) ... var BlogId = item.BlogId;
This has solved the issue. I now have the complete lists of comments for each (BlogId) parent blog post. I really appreciate your help and am marking your last response as answer.
Thanks again!
RC
Tuesday, July 23, 2019 1:54 PM