Serializing a PartialView as JSON in ASP.NET MVC
[tweetmeme style=”compact”]In certain situations you might want to make an AJAX request to load a Partial View (UserControl) and display in a web page. It was quite easy to accomplish that using AJAX.NET Update Panels. Though jQuery doesn’t have any Update Panels of its own, it is quite easy to accomplish the same. In this post, I will try to make an AJAX request to fetch a UserControl as JSON and display it on the screen. Alright, so follow me…
1) Create a Partial View name PostList as follows…
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Post>>" %> <table border="0" width="100%"> <thead> <tr> <th> Post ID </th> <th> Title </th> <th> Description </th> <th> Created On </th> </tr> </thead> <tbody> <%foreach (MyMVCTrials.Models.Post p in Model) { %> <tr> <td> <%=p.PostID.ToString() %> </td> <td> <%=p.Title %> </td> <td> <%=p.Description %> </td> <td> <%=p.CreatedOn %> </td> </tr> <%} %> </tbody> </table>
2) Create a Entity class named Post as follows…
public class Post { public int PostID { get; set; } public string Title { get; set; } public string Description { get; set; } public string CreatedOn { get; set; } }
3) Create a private method in the Controller class, say PostController, to prepare a List of Posts and return it.
private IList<Post> GetPosts() { IList<Post> posts = new List<Post>(); for (int i = 1; i <= 10; i++) { Post post = new Post(); post.PostID = i; post.Title = String.Format("My Post Title #{0}", i.ToString()); post.Description = String.Format("My Description {0}", i.ToString()); post.CreatedOn = DateTime.Now.ToLongDateString(); posts.Add(post); } return posts; }
4) Create a private method in your Controller which will execute the PartialView and return a JSON string of the view.
private JsonResult SerializeControl(string controlPath, object model) { ViewPage page = new ViewPage(); ViewUserControl ctl = (ViewUserControl)page.LoadControl(controlPath); page.Controls.Add(ctl); page.ViewData.Model = model; page.ViewContext = new ViewContext(); System.IO.StringWriter writer = new System.IO.StringWriter(); System.Web.HttpContext.Current.Server.Execute(page, writer, false); string outputToReturn = writer.ToString(); writer.Close(); return this.Json(outputToReturn.Trim()); }
5) Create the following Action Methods in your Controller
//Returns the View that will display the List of Posts based on an AJAX call. public ActionResult Index() { return View(); } //Returns the serialized JSON string of the partial view, PostList public JsonResult PostList() { System.Threading.Thread.Sleep(3000); return SerializeControl("~/Views/Shared/PostList.ascx", GetPosts()); }
6) And finally, in our Index View Page, add the following…
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <script type="text/javascript"> $(document).ready(function() { $("#loadPosts").click(function() { $("#postList").html("Loading Posts...."); $.getJSON("/Home/PostList", function(data) { if (data) { $("#postList").html(data); } }); }); }); </script> <input type="button" id="loadPosts" value="Load Posts!" /> <div id="postList" /> </asp:Content>
When you run the application, here is how it will look like…
On clicking the button
Final result!
[…] Serializing a PartialView as JSON in ASP.NET MVC (tags: aspnetmvc, asp.net mvc, jquery) […]
only after setting JsonRequestBehavior, it worked!!
return Json(data, JsonRequestBehavior.AllowGet)
anyway thanks for your code!
Just for fun, take the post title and try to turn it into a link via Html.ActionLink. Throws NotImplemetedException. Oddly, Html.Encode works. Bears investigation.
How to do it for Razor engine
Excellent! Thanks a lot, your post really helped.
Why Mine stops at Loading Posts…. I made sure I have loaded jquery and jquery-unobtrusive-ajax.cs The following are the code. Please help.
PostController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace TestPartialView.Controllers
{
public class PostController : Controller
{
//
// GET: /Post/
public ActionResult Index()
{
return View();
}
//Returns the serialized JSON string of the partial view, PostList
public JsonResult PostList()
{
System.Threading.Thread.Sleep(3000);
return SerializeControl(“~/Views/Shared/PostList.cshtml”, GetPosts());
}
private JsonResult SerializeControl(string controlPath, object model)
{
ViewPage page = new ViewPage();
ViewUserControl ctl = (ViewUserControl)page.LoadControl(controlPath);
page.Controls.Add(ctl);
page.ViewData.Model = model;
page.ViewContext = new ViewContext();
System.IO.StringWriter writer = new System.IO.StringWriter();
System.Web.HttpContext.Current.Server.Execute(page, writer, false);
string outputToReturn = writer.ToString();
writer.Close();
return this.Json(outputToReturn.Trim(),JsonRequestBehavior.AllowGet);
}
private IList GetPosts()
{
IList posts = new List();
for (int i = 1; i <= 10; i++)
{
Post post = new Post();
post.PostID = i;
post.Title = String.Format("My Post Title #{0}", i.ToString());
post.Description = String.Format("My Description {0}", i.ToString());
post.CreatedOn = DateTime.Now.ToLongDateString();
posts.Add(post);
}
return posts;
}
}
public class Post
{
public int PostID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string CreatedOn { get; set; }
}
}
/Post/Index.cshtml:
@model IEnumerable
@{
ViewBag.Title = “Index”;
Layout = “~/Views/Shared/_Layout.cshtml”;
}
Index
$(document).ready(function() {
$(“#loadPosts”).click(function() {
$(“#postList”).html(“Loading Posts….”);
$.getJSON(“/Home/PostList”, function(data) {
if (data) {
$(“#postList”).html(data);
}
});
});
});
Post.cs: in Models:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace TestPartialView.Models
{
public class Post
{
public int PostID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string CreatedOn { get; set; }
}
}
and finally in all the directory of /Post /Home /Shared, I have PostList.cshtml:
@model IEnumerable
Post ID
Title
Description
Created On