How do I render an ASP.NET MVC Razor view to a string?

Posted: (EET/GMT+2)

 

Razor aka CSHTML technology is a nice way to generate HTML views. But sometimes, you don't need the HTML for the browser, instead, you might need the rendered HTML to something else, like an email body or a PDF generation component. In this situations, it's nice to know how to render a Razor view as a string. Here's a small helper for classic ASP.NET MVC 5.

// MVC 5: render a view to string
public static string RenderViewToString(
  ControllerContext context, string viewName, object model)
{
    context.Controller.ViewData.Model = model;

    using (StringWriter sw = new StringWriter())
    {
        var result = ViewEngines.Engines.FindView(context, viewName, null);
        ViewContext viewContext = new ViewContext(
            context,
            result.View,
            context.Controller.ViewData,
            context.Controller.TempData,
            sw
        );

        result.View.Render(viewContext, sw);
        return sw.ToString();
    }
}

Usage:

// inside a Controller
string html = RenderViewToString(this.ControllerContext,
                "Email/OrderConfirmation", model);
// send "html" out via your emailing logic

ASP.NET Core 2 needs the view engine service:

// ASP.NET Core: IRazorViewEngine based helper
public class ViewRenderService
{
    private readonly IRazorViewEngine _engine;
    private readonly ITempDataProvider _tempData;
    private readonly IServiceProvider _services;

    public ViewRenderService(IRazorViewEngine engine,
      ITempDataProvider tempData, IServiceProvider services)
    {
        _engine = engine; _tempData = tempData; _services = services;
    }

    public async Task<string> RenderAsync(
      ActionContext actionContext, string viewPath, object model)
    {
        var viewResult = _engine.GetView(executingFilePath: null,
                           viewPath: viewPath, isMainPage: true);
        if (!viewResult.Success) throw new FileNotFoundException(viewPath);

        var view = viewResult.View;
        using (var sw = new StringWriter())
        {
            var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider(),
                             new ModelStateDictionary()) { Model = model };
            var tempData = new TempDataDictionary(actionContext.HttpContext, _tempData);
            var vc = new ViewContext(actionContext, view, viewData, tempData,
                           sw, new HtmlHelperOptions());

            await view.RenderAsync(vc);
            return sw.ToString();
        }
    }
}

Hope this helps!