2

I have an app that only ever loads a full view one time. My reason for doing this is not important. What is important is that the rest of the content is only ever going to come back in partial views. In addition to some content I have some JSON objects I'd like to pass back and forth to and from the server with each AJAX request.

Is there a way to return a JSON object with a view as one of its properties? This would be extremely useful and would save on bandwidth as my current workaround is to make two ajax calls, one for the JSON and one for the partial view which not only takes more time and more bandwidth, but it also requires two separate action methods and some fancy tricks on the server side. Serializing a view into a JSON object would solve all my problems.

What is the best way to accomplish this and what downsides (if any) would there be to doing this?

CatDadCode
  • 58,507
  • 61
  • 212
  • 318

2 Answers2

3

You can render the view from the controller and return it with the JSON object back to the client.

If you will use my simple helper to render ActionResult to a string then your code will look like:

public JsonResult DoSomething() {
    var viewString = View().Capture(ControllerContext);
    return new JsonResult {
        JsonRequestBehavior = JsonRequestBehavior.AllowGet,
        Data = new {
            time = DateTime.Now,
            html = viewString
        }
    };
}
Dmytrii Nagirniak
  • 23,696
  • 13
  • 75
  • 130
  • I think maybe you misunderstand. I want to include an asp.net MVC partial view inside of a action method that returns JsonResult. You can't just put a ViewResult into a JsonResult as far as I know. How do you turn the view into a string and tack it onto the jsonresult? – CatDadCode Nov 11 '10 at 04:23
  • I have updated the answer. It should work for you. I would appreciate I you could rate/share my blog post as I did it to specifically answer this question :) – Dmytrii Nagirniak Nov 11 '10 at 06:09
  • View() doesn't appear to have a method called Capture. I found what I needed anyway and posted it as an answer to my own question. Thanks for the help. – CatDadCode Nov 11 '10 at 08:55
  • The `Capture` is an extension method. Just follow the article I posted. It really is that simple. – Dmytrii Nagirniak Nov 11 '10 at 09:54
  • @DmytriiNagirniak Your solution works for all ActionResult and the method is very useful in many cases. Vote up! – Tomas Aug 08 '12 at 07:04
2

Here's an interesting tidbit of code that seems to do what I want and preserves model binding from what I can tell.

protected string RenderPartialViewToString(string viewName, object model)
{
     controller.ViewData.Model = model;

     using (StringWriter sw = new StringWriter())
     {
          ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
          ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
          viewResult.View.Render(viewContext, sw);

          return sw.GetStringBuilder().ToString();
     }
}

Works like a charm. I just use this and pass the string as a JSON parameter and then on the client I read the parameter and drop it in it's appropriate container. I'm very excited to have this working.

CatDadCode
  • 58,507
  • 61
  • 212
  • 318