How to Render Partial View into a String

I opted for an extension method like the following for an ASP.NET MVC 4 app. I think it's simpler than some of the suggestions I've seen:

public static class ViewExtensions
{
    public static string RenderToString(this PartialViewResult partialView)
    {
        var httpContext = HttpContext.Current;

        if (httpContext == null)
        {
            throw new NotSupportedException("An HTTP context is required to render the partial view to a string");
        }

        var controllerName = httpContext.Request.RequestContext.RouteData.Values["controller"].ToString();

        var controller = (ControllerBase)ControllerBuilder.Current.GetControllerFactory().CreateController(httpContext.Request.RequestContext, controllerName);

        var controllerContext = new ControllerContext(httpContext.Request.RequestContext, controller);

        var view = ViewEngines.Engines.FindPartialView(controllerContext, partialView.ViewName).View;

        var sb = new StringBuilder();

        using (var sw = new StringWriter(sb))
        {
            using (var tw = new HtmlTextWriter(sw))
            {
                view.Render(new ViewContext(controllerContext, view, partialView.ViewData, partialView.TempData, tw), tw);
            }
        }

        return sb.ToString();
    }
}

It allows me to do the following:

var html = PartialView("SomeView").RenderToString();

Also, this approach persists any Model, ViewBag and other view data for the view.


DaveDev's answer worked well for me, however when the partial view calls another partial I get "Value cannot be null. Parameter name: view"

Searching around I have made a variant of the following that seems to work well.

 public static string RenderPartialToString(string viewName, object model, ControllerContext ControllerContext)
    {
        if (string.IsNullOrEmpty(viewName))
            viewName = ControllerContext.RouteData.GetRequiredString("action");
        ViewDataDictionary ViewData = new ViewDataDictionary();
        TempDataDictionary TempData = new TempDataDictionary();
        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();
        }

    }

Usage:

String result = MVCHelpers.RenderPartialToString("PartialViewHere", Model, ControllerContext)

This is a slightly modified version of an answer that works:

public static string RenderPartialToString(string controlName, object viewData)
{
    ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() };

    viewPage.ViewData = new ViewDataDictionary(viewData);
    viewPage.Controls.Add(viewPage.LoadControl(controlName));

    StringBuilder sb = new StringBuilder();
    using (StringWriter sw = new StringWriter(sb))
    {
        using (HtmlTextWriter tw = new HtmlTextWriter(sw))
        {
            viewPage.RenderControl(tw);
        }
    }

    return sb.ToString();
}

Usage:

string ret = RenderPartialToString("~/Views/MyController/MyPartial.ascx", model);