Question

What is the best approach to take when converting a basic ActionResult to JSON objects and rendering them in a PartialView? My objective is to modify the application so that instead of the page rendering only the comments in the db at the time of the page request to a type of data service that updates thePartialView to add any incoming comments that may have been posted since the last page request. I think the solution I am looking for will use OData in json format and then bind that data using knockout.js, but not sure.

Here is the Controller ActionResult which returns an IEnumerable list of objects from the repository to a PartialView:

        [ChildActionOnly]
        public ActionResult GetCommentsById(int AId = 0)
        {

            if (AId == 0)
                return HttpNotFound();

            return PartialView("_CommentsPartial",  
            _unitOfWork.ArticleRepository.GetCommentsByArticleId(AId));
        }

Here is a snippet of the PartialView to keep things short:

@model IEnumerable<BlogSite.Models.Comment>
@using BlogSite.Helpers;

<ul id="comments-list">

    @{

        foreach (var comment in Model)
        {
            <!--Grabs Parent Comment and then all replies w/ParentCommentId b4 grabs new Parent Comment -->
            if (comment.isRoot && comment.ParentCommentId == null)
            {
                <!-- Comment -->
                int counter = 0; foreach (var c in Model) { if (c.ParentCommentId == comment.CommentId) { counter += 1; } }
                <li id="@comment.CommentId" itemscope itemtype="http://schema.org/UserComments" class="comment-container" tabindex="@comment.CommentId">

Then I call it from the Details view:

<div id="comments-panel" class="panel-box">

    <div class="show-comments"><div id="upNdown"></div><span id="showNhide">Show Comments</span></div><br />  <br />

    <div id="comments-partial" style="display:none;">
        @Html.Action("AddComment", "Comment", new { AId = Model.ArticleId })
        @Html.Action("GetCommentsById", "Article", new { AId = Model.ArticleId })
    </div>

</div>

How can I make this conversion as painless as possible? Thanks in advance!

Was it helpful?

Solution

I think I gather from your question that the controller already did its work and that you simply want to "consume" the data output from it as if it were an AJAX request using the same js code. You can do this fairly easily by just serializing the data in the model using the Newtonsoft Json.NET api and extensions provided by Forloop.HtmlHelpers. These can be installed as nuget packages if you haven't already.

First, you would place this in your partial view
Note: If you don't want to install the Newtonsoft package you can replace JsonConvert.SerializeObject with the System.Web.Helpers method Json.Encode

@{
    using (var context = Html.BeginScriptContext())
    {
        Html.AddScriptBlock("var jsonData=" + JsonConvert.SerializeObject(Model) + ";");
    }
}

Then in your layout page, to ensure that your script block is rendered at the appropriate time, add this call to Html.RenderScripts

@Scripts.Render("~/bundles/jquery")
@*Add any other dependency scripts*@

@Html.RenderScripts()

@RenderSection("scripts", required: false)

This is why you need the Forloop.HtmlHelpers package, these extension methods help mitigate out-of-order script code getting rendered in the partial view before jQuery or anything else has started up.

Hope that helps

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top