Home > ASP.NET MVC > ASP.NET MVC Render Partial View to String

ASP.NET MVC Render Partial View to String


I have run into a situation where I would like to render a partial view to a string and then return it as part of a JSON response like so:

return Json(new {
    statusCode = 1,
    statusMessage = "The person has been added!",
    personHtml = PartialView("Person", person)
});

The ability to do something like this would open up a ton of amazing possibilities, so I really scoured the internet looking for a solution. Unfortunately, no one seems to have come up with a clean solution for it, so I dug into the MVC code and came up one…and because I’m such a nice guy, you get to copy it for free. ;)

public abstract class MyBaseController : Controller {

    protected string RenderPartialViewToString()
    {
        return RenderPartialViewToString(null, null);
    }

    protected string RenderPartialViewToString(string viewName)
    {
        return RenderPartialViewToString(viewName, null);
    }

    protected string RenderPartialViewToString(object model)
    {
        return RenderPartialViewToString(null, model);
    }

    protected string RenderPartialViewToString(string viewName, object model)
    {
        if (string.IsNullOrEmpty(viewName))
            viewName = ControllerContext.RouteData.GetRequiredString("action");

        ViewData.Model = model;

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

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

Now you can simply do this:

public class MyController : MyBaseController {

    public ActionResult CreatePerson(Person p) {
        if (ModelState.IsValid) {
            try {
                PersonRepository.Create(p);
                return Json(new {
                    statusCode = 1,
                    statusMessage = "The person has been added!",
                    personHtml = RenderPartialViewToString("Person", p)
                });
            }
            catch (Exception ex) {
                return Json(new {
                    statusCode = 0,
                    statusMessage = "Error: " + ex.Message
                });
            }
        }
        else
            return Json(new {
                statusCode = 0,
                statusMessage = "Invalid data!"
            });
    }
}

Also note that you can modify these functions to render a View (rather than a PartialView) with this small change:

ViewEngineResult viewResult = ViewEngines.Engines.FindView(ControllerContext, viewName);

Enjoy!

kick it on DotNetKicks.com

About these ads
Categories: ASP.NET MVC
  1. May 20, 2010 at 6:51 am

    Thank you, this is exactly what I was after.

    Rich

  2. Josh
    May 20, 2010 at 9:39 am

    AWESOME, This was excactly what I was trying to do.

    Thanks!

    Josh

  3. Josh
    May 20, 2010 at 9:44 am

    Just as an update, you could wrap the StringWriter inside a using statement:

    protected string RenderPartialViewToString(string viewName, object model)
    {
    if (string.IsNullOrEmpty(viewName))
    viewName = ControllerContext.RouteData.GetRequiredString(“action”);

    ViewData.Model = model;

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

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

    • May 20, 2010 at 9:50 am

      Good idea, Josh. I will update the post. Thanks. :)

  4. June 23, 2010 at 9:51 pm

    thanks, i looking for long time :)

  5. Panos
    June 25, 2010 at 4:01 am

    :D Hey, nice. Thanks for the source!

  6. July 15, 2010 at 9:15 am

    Thanks, just needed exactly the same thing in same scenario :)

  7. Joris
    July 16, 2010 at 6:38 am

    I would love to use this solution, but I am running into an error!

    viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);

    Error 80 ‘System.Web.Mvc.ViewContext’ does not contain a constructor that takes ‘5’ arguments

    Am I forgetting something?

    • July 16, 2010 at 9:19 am

      Joris,

      This solution was implemented with ASP.NET MVC 2. Maybe you need to upgrade?

  8. August 24, 2010 at 11:27 am

    awesome! thanks much. this is what i was looking for :-)

  9. ewb
    September 10, 2010 at 1:32 am

    Nice work – thanks for sharing this.

  10. TimC
    September 13, 2010 at 6:32 am

    Brilliant,

    I’ve tried a whole bunch of different solutions and this is the best and simplest. Supports embedded Html helpers too.

  11. Ze
    September 13, 2010 at 12:17 pm

    thank you so much… You’ve saved me and my team. thank you for sharing this pearl ;)

  12. Michael Reyeros
    September 29, 2010 at 3:13 pm

    Is there any way for calling a partial view in a different controller?

    • September 29, 2010 at 3:21 pm

      If you’re asking how to render a View that is located on another controller path, I’m pretty sure you can just do this:

      RenderPartialViewToString(“~/Path/To/View.aspx”)

      I hope that answers your question.

  13. October 23, 2010 at 3:53 am

    This is a pretty good solution it helped a lot with validating partial views but it pollutes your inheritance hierarchy.

    I’ve rewritten it as a C# extension method. You can find it on my blog (learningdds.com) or directly from here:
    http://learningdds.com/public/ControllerExtension.cs

    Hope this is helpful.

  14. October 27, 2010 at 9:46 am

    Excellent job, thanks!

  15. kdawg
    November 9, 2010 at 5:31 pm

    love it, thanks so much!

  16. Kip
    November 15, 2010 at 6:19 am

    I’ve the same problem that Joris has. I use ASP.NET MVC 1 and all the team use it, so I can’t upgrade it to ASP.NET MVC 2.0, any ideas ?

    • December 3, 2010 at 9:31 am

      Kip, I would suggest digging through the MVC code. It is open source and that is exactly what I did to come up with this solution. MVC 1 probably isn’t that much different. Find the code that renders a view and then just copy/modify the code around it into a utility function that you can use to render partials.

  17. John
    February 8, 2011 at 6:23 am

    I was trying to do this very thing but was getting stuck. Your article helped me out!

  18. John
    February 17, 2011 at 7:04 am

    A solution with HtmlHelper extension method, but not tested in all situation for the moment …

    public static string RenderPartialToString(this HtmlHelper html, string viewName, object viewData)
    {
    var baseOutput = html.ViewContext.Writer;

    StringWriter sw = new StringWriter();

    try
    {
    html.ViewContext.Writer = sw;
    html.RenderPartial(viewName, viewData);
    }
    catch(Exception ex )
    {
    html.ViewContext.Writer = baseOutput;
    sw.Dispose();
    return ex.Message + ex.StackTrace;
    }

    html.ViewContext.Writer = baseOutput;
    sw.Flush();
    return sw.ToString();
    }

  19. February 24, 2011 at 5:51 am

    Wouldn’t an extension to ViewResultBase be neater? e.g. in the Controller:

    var viewText = View().RenderToString(this);

    var partialViewText = PartialView().RenderToString(this);

    // or with a named view and model

    var namedViewText = View(“Index”, model).RenderToString(this);

    the extension method would then just be

    public static string RenderToString(this ViewResultBase viewResult, Controller controller)
    {
    // init string writer
    using (StringWriter sw = new StringWriter())
    {
    // get the view context
    var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);

    // render the view
    viewResult.View.Render(viewContext, sw);

    // return the string
    return sw.ToString();
    }
    }

    and you’d only require one

  20. February 24, 2011 at 6:18 am

    I’ve just realised this won’t quite work as the viewResult.View property will be null without a call to ViewEngineCollection.FindView or FindPartialView so we would need two methods, one for ViewResult and one for PartialViewResutl and before the line where we create the ViewContext we’d need to call either:

    viewResult.View = viewResult.ViewEngineCollection.FindView(controller.ControllerContext, viewResult.ViewName, viewResult.MasterName).View;

    or

    viewResult.View = viewResult.ViewEngineCollection.FindPartialView(controller.ControllerContext, viewResult.ViewName).View;

    Serves me right for posting without checking the code

  21. Paulie
    February 24, 2011 at 9:15 am

    Sweet as Terry Nutkins!

    Great for returning json status, messages and some markup to be insterted onto the page.

  22. John
    February 24, 2011 at 11:17 am

    I have made this extension to HtmlHelper classe because I don’t call Render() and RenderPartial() in Controller / View, I call render in my own classes which have a reference to the ViewPage HtmlHelper.

    I have an HtmlHelper extension which initialize my own control factory, and this control factory give the reference of the Htmlhelper to all controls created by this factory.

  23. Ryan
    February 28, 2011 at 10:57 pm

    Thanks. Exactly what I needed!

  24. al
    March 8, 2011 at 8:32 am

    Awsome cant wait to try….wondering if i have no update target, i can’t really use the client side validation that mvc2 has..which sucks

  25. david
    April 19, 2011 at 5:31 pm

    Cheers, thanks for sharing this. You have saved me a lot of time!

  26. April 25, 2011 at 11:09 pm

    Thanks. Like everyone else, just what I was looking for. You really are a nice guy!
    PS. And a lovely couple!

  27. InfoNeeded
    May 5, 2011 at 8:21 am

    I am new to MVC. Can anyone please post an example of how to use the json html result in view. Thanks.

    • May 5, 2011 at 9:07 am

      Consuming the JSON result actually has very little to do with MVC. It will be consumed via JavaScript. You will make an AJAX request to the server and then process the result accordingly. For example, if you have an MVC action that returns the same result I used in my blog post, then you can consume the result using jQuery as follows:

      $.post(‘/addUser’, userData, function(result) {
      alert(result.statusMessage);
      if (result.statusCode == 1) {
      var newPerson = $(result.personHtml);
      $(“#people”).append(newPerson);
      }
      });

  28. Navaneeth
    May 25, 2011 at 2:14 am

    That’s great.

  29. June 10, 2011 at 2:34 am

    Thanks for sharing, helps a lot.

  30. June 16, 2011 at 9:35 pm

    Great, it even works in MVC3.

  31. June 27, 2011 at 3:41 pm

    Amazing. Thanks.

  32. Ethan
    June 30, 2011 at 8:18 pm

    Good job mate. Exactly the case I need. Thanks

  33. July 26, 2011 at 10:16 pm

    I’ve been searching a while for this. Exactly what I needed. Huge thanks!

  34. polarwarp
    August 25, 2011 at 8:58 pm

    I wish we were using MVC 2.0. As

    viewResult.View.Render(viewContext, sw);

    Doesn’t write anything to my streamwriter. I’ve seen another solution where it mucks around with fake contexts, but I need session variables in my view so it errors if I try doing that. :(

  35. September 5, 2011 at 8:24 pm

    Thanks very much for sharing that Kevin. Very much appreciated.

  36. October 7, 2011 at 8:25 am

    Works like a charm, thank you so much!

  37. October 17, 2011 at 11:34 pm

    Hi All,

    Just more than awesome!!!

    What a great article!!

    Thanks to all for sharing!!

    Thanks,

    Amol

  38. October 20, 2011 at 4:22 am

    You really are such a nice guy =D

  39. October 31, 2011 at 3:11 am

    I need to render partial views to build a CMS. I want to dynamically load views (from a place where user installs modules, which are in essence, ASP.NET MVC Views) and then render them in the server (execute them, and get the result out of them), and then put it inside the specified place. Your code was a good starting point for me. However, still I’m not able to figure out how to do that. Thanks.

  40. November 25, 2011 at 3:19 am

    Thank you for such nice article :)
    It has helped me a lot.

  41. Sanjay Sharma
    December 8, 2011 at 4:47 am

    Thanks buddy.

    After a struggle of 2 days, this was the best and simple one.

    Thanks a lot

  42. happinesshunter
    December 23, 2011 at 4:42 am

    great article , you save me alot

  43. December 30, 2011 at 2:59 am

    Wonderful. Here my edited version so code can be moved outside the controller (maybe in a helper file)

    public static string RenderViewToString(ControllerContext context, ViewDataDictionary viewData, TempDataDictionary tempData, string viewName, object model)
    {
    if (string.IsNullOrEmpty(viewName))
    viewName = context.RouteData.GetRequiredString(“action”);

    viewData.Model = model;

    using (StringWriter sw = new StringWriter())
    {
    ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(context, viewName);
    ViewContext viewContext = new ViewContext(context, viewResult.View, viewData, tempData, sw);
    viewResult.View.Render(viewContext, sw);

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

    Then can be called from the controller like this:

    MyHelper.RenderViewToString(this.ControllerContext, this.ViewData, this.TempData, “_PartialViewName”, MyObject)

    In my case I made two versions, one requiring only the controller, viewname and model, since in most of the cases we only need to render simple partial views that work with model or viewmodel.

  44. January 3, 2012 at 3:08 am

    Thanks for sharing. Just what I needed.

  45. Jim D
    January 18, 2012 at 5:50 am

    Great article – thanks!

    Anybody know how to do this outside of web apps / MVC, e.g. in a WinForms app or console app?

  46. January 19, 2012 at 9:30 am

    Couldn’t you achieve the same thing making a View with JSON in it?

    • January 19, 2012 at 3:22 pm

      Probably, but its more work, especially if you need to do it often. Its also not really a traditional use of the view considering ASP.NET MVC has JSON functionality built right into the controller. Good suggestion, though!

  47. Curious
    February 9, 2012 at 8:54 pm

    Just wondering if you got the RenderViewToString from the StackOverflow post that predates it, here: http://stackoverflow.com/questions/483091/render-a-view-as-a-string/2759898#2759898

    Looks pretty similar.

    • February 9, 2012 at 11:33 pm

      Nope, didn’t get it from there. It took me several hours of digging through the MVC code to come up with my solution. I’m guessing you came up with your solution in the same manner, which is why they are so similar.

  48. Andre
    February 15, 2012 at 2:22 pm

    Exactly what I was looking for..Thanks for posting

  49. February 15, 2012 at 4:28 pm

    Thanks for the code, this help a lot. Is there a way to remove the tabs and line breaks (“\r”, “\n”, “\t”, etc…) from the result?

    • Jim Maguire
      March 25, 2012 at 4:06 pm

      This really helped me, thanks. Here’s how I removed the “\r”…etc:

      Change to return MvcHtmlString:
      public static MvcHtmlString RenderViewToString(ControllerContext context, string viewName, object model)

      return MvcHtmlString.Create(sw.GetStringBuilder().ToString());

      Here’s the entire:

      public static MvcHtmlString RenderViewToString(ControllerContext context, string viewName, object model)
      {
      if (string.IsNullOrEmpty(viewName))
      viewName = context.RouteData.GetRequiredString(“action”);

      ViewDataDictionary viewData = new ViewDataDictionary(model);

      using (StringWriter sw = new StringWriter())
      {
      ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(context, viewName);
      ViewContext viewContext = new ViewContext(context, viewResult.View, viewData, new TempDataDictionary(), sw);
      viewResult.View.Render(viewContext, sw);

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

  50. adam
    February 23, 2012 at 5:22 pm

    Hey, this is super helpful. I’m having some trouble unit testing it, though; I need to somehow mock the ViewEngines.Engines.FindPartialView(ControllerContext, viewName) call. Mocking up up a fake ControllerContext is straightforward enough, but I can’t find a way to set something up for the FindPartialView method.

    I’ve tried http://stackoverflow.com/questions/3621961/asp-net-mvc-unit-testing-renderpartialviewtostring-with-moq-framework, but without luck (what is the RouteConfigurator class?) and http://www.atlanticbt.com/blog/asp-net-mvc-using-ajax-json-and-partialviews/ (similar idea, same problem). Any thoughts? How did you unit test your example?

    • August 2, 2012 at 8:52 am

      Did you ever figure out how to unit test this? I’m having the same issue.

  51. wolverine
    March 5, 2012 at 3:46 pm

    It works fine if I don’t have a nested partial. If I have @Html.Partial(“_PartialName”, Model) instead of a partial that is rendered to string, it leaves out the nested partial.

    Any suggestions?

  52. wolverine
    March 5, 2012 at 6:41 pm

    How can I get a nested partial view to render with this logic?

    Ex. From a partial with name “_ParentPartial”

    @Html.Partial(“_ChildPartialName”, Model)

    • wolverine
      March 6, 2012 at 5:35 pm

      Nevermind, some of my logic excluded the partial from rendering. Works like a charm!

  53. ranjez
    April 3, 2012 at 3:08 am

    Hi Just wondering why you wouldn’t just do

    return sw.ToString();

    rather than

    return sw.GetStringBuilder().ToString();

  54. anyeone
    May 24, 2012 at 4:55 pm

    I also am having trouble unit testing this – please post how you unit tested it (or verify that you didn’t)

  55. July 16, 2012 at 4:27 am

    Hi Kevin,

    This was just what I was looking for. I ended up writing a blog post about my own use of this technique and why it was useful to me. I’ve clearly linked back to you here; I hope that’s okay. You can read the blog post here:

    http://icanmakethiswork.blogspot.com/2012/07/rendering-partial-view-to-string.html

    Thanks again – you’ve saved me some hard work!

    • July 16, 2012 at 1:06 pm

      Thanks for the backlink. I’m glad it helped you out. :)

  56. Suresh
    July 18, 2012 at 4:21 am

    Good post thanks!. However when the partial view is rendering it is adding extra blank spaces.
    eg:

    please look at the value attribute of the input element.

    Have any idea?

  57. July 24, 2012 at 5:39 am

    Awesome, of all the solutions I found this is the only one which actually worked as expected

  58. Ricky
    September 26, 2012 at 3:04 am

    Extremely you’re such a nice guy. :)

  59. October 19, 2012 at 2:43 pm

    I get always an exception in the .Render() method that something in the writer object is null. I use mvc 4.0. Any ideas?

  60. December 4, 2012 at 5:37 am

    the best solution on the net to this issue, thanks for posting!!

  61. timn48
    December 4, 2012 at 6:50 am

    best solution on the net, thanks for posting!

  62. December 26, 2012 at 5:26 am

    Hey Crafty.

    Thanks for your article which had helpled me in rendering the partial view as string from controller.
    But is there any way to UnitTest this method as i am having nightmare in testing this method.
    If you already have any sample that would really help me a lot..

    Thank you

  63. January 18, 2013 at 10:57 am

    You are a hero.

  1. October 11, 2010 at 6:49 am
  2. October 23, 2010 at 3:37 am
  3. June 18, 2011 at 4:16 pm
  4. September 1, 2011 at 9:24 am
  5. October 2, 2011 at 12:48 am
  6. March 17, 2012 at 2:09 pm
  7. June 28, 2012 at 6:35 am
  8. September 19, 2012 at 6:54 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: