Saturday, November 2, 2013

MVC Partial View to String

Sometimes, I would have some page features that would require fetching HTML on the fly from the server and at the same time the user needs to be notified why the fetching failed from the server.

Suppose that I need to populate a tag in the following HTML:

   <!-- the div tag -->
   <div id='someDivToPopulate'>&nbsp;</div>
    <!-- button to click -->
   <button id='someButton'>click me </button>
    <!-- the javascript to click event and fetching of the JSON Data -->
   <script type='text/javascript'>
       $('#someButton').click(function () {
           $.post(
               "SomeController/GetSomeJsonData",
               {
                   Id: 1
               },
               function (data) { 
                   if (!data.Success) {
                       alert(data.Message);
                       return;
                   }
                   $("#someDivToPopulate").html(data.View);
               });
       });
   </script>

I have pages that makes AJAX requests to have the server return views in HTML string in JSON format.

Typically, my JSON response object would contain properties such as follows:

Figure 1:
//A success response:
{
   Success: true,
   Message: "success",
   View: "{some html string}"
}

//A failure response:
{
   Success: false,
   Message: "record not found",
   View: null
}


Well, Asp.Net MVC makes it supper easy to have such HTML generated from a partial view

Figure 2:

public class SharedController : Controller
    {
  public static string RenderViewToString(ControllerContext context, string viewName, object model)
  {
   //if view name is not specified, use action name
   if (string.IsNullOrEmpty(viewName))
    viewName = context.RouteData.GetRequiredString("action");

   // get view data from model
   var viewData = new ViewDataDictionary(model);

   //render the view and generate HTML string
   using (var sw = new StringWriter())
   {
    var viewResult = ViewEngines.Engines.FindPartialView(context, viewName);
    var viewContext = new ViewContext(context, viewResult.View, viewData, new TempDataDictionary(), sw);
    viewResult.View.Render(viewContext, sw);

    return sw.GetStringBuilder().ToString();
   }
  }
    }
 
You can define this method in shared controller class or in a helper class so any other class can use it too.

The usage of this is quite simple: using out example in Figure 1, suppose I have a controller with the following action.

Figure 3:

[HttpPost]
public ActionResult GetSomeJsonData(SomeRequestModel model)
{
 var someViewModel = AutoMapper.Mapper.Map<SomeDomainModel, SomeReturnModel>(_someRepo.GetById(model.Id));
 var someViewInHtml = RenderViewToString(ControllerContext, "someView", someViewModel);
 var toReturn = new { Success = true, Message = "success", View = someViewInHtml };
 return Json(toReturn);
} 

Note: remember when returning JSON data, be sure to include exactly only what the view needs not more especially if your site is open to the public.   
Otherwise, one ends sending sensitive information to the browser.
 

About Cullen

My photo
Christian, Father, Software Developer/Architect who enjoys technology and using it to make people's lives easier!

Followers