Render Razor view to string in ASP.NET 5

15,922

Solution 1

I use the following types injected from the IServiceProvider:

ICompositeViewEngine viewEngine;
ITempDataProvider tempDataProvider;
IHttpContextAccessor httpContextAccessor;

I render the content using the following method:

private async Task<string> RenderView(string path, ViewDataDictionary viewDataDictionary, ActionContext actionContext)
{
    using (var sw = new System.IO.StringWriter())
    {
        var viewResult = viewEngine.FindView(actionContext, path);

        var viewContext = new ViewContext(actionContext, viewResult.View, viewDataDictionary, new TempDataDictionary(httpContextAccessor, tempDataProvider), sw);

        await viewResult.View.RenderAsync(viewContext);
        sw.Flush();

        if (viewContext.ViewData != viewDataDictionary)
        {
            var keys = viewContext.ViewData.Keys.ToArray();
            foreach (var key in keys)
            {
                viewDataDictionary[key] = viewContext.ViewData[key];
            }
        }

        return sw.ToString();
    }
}

I call it like this:

var path = "~/Views/Home/Index.cshtml";
var viewDataDictionary = new ViewDataDictionary(new Microsoft.AspNet.Mvc.ModelBinding.EmptyModelMetadataProvider(), new Microsoft.AspNet.Mvc.ModelBinding.ModelStateDictionary());
var actionContext = new ActionContext(httpContextAccessor.HttpContext, new Microsoft.AspNet.Routing.RouteData(), new ActionDescriptor());
viewDataDictionary.Model = null;
var text = await RenderView(path, viewDataDictionary, actionContext);

Of course, my viewDataDictionary and actionContext variables are set by another method for encapsulation. A modification to the new ViewDataDictionary line can result in a typed Model being bound to your View if you choose.

This code uses heavy usings, I think I've listed them below. Otherwise, VS2015 is pretty good about finding them.

using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Rendering;

This was written under beta-3; it still builds, but some things may change. I'll try to come back here to update if it does.

Solution 2

There is a solution that I've used an year ago. I'm not sure if there is a new/better way to do, but it solves the problem.

public string RenderViewToString(string viewName, object model)
{
    ViewData.Model = model;
    using (var sw = new StringWriter())
    {
       var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
       var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
       viewResult.View.Render(viewContext, sw);
       viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
       return sw.GetStringBuilder().ToString();
     }
}
Share:
15,922

Related videos on Youtube

user1620696
Author by

user1620696

Updated on June 21, 2022

Comments

  • user1620696
    user1620696 almost 2 years

    In previous versions of ASP.NET it was possible, although not very simple, to render Razor views as strings. The methods I've seem are to use a fake controller, or also to use some external engine like RazorEngine.

    Now, many things are changed with ASP.NET 5 and I was wondering whether or not this is now simpler than before. So in the new version of the framework is there one straightforward way to render Razor views as strings or we still need to use the methods from the previous versions?

    • Fabio Luz
      Fabio Luz almost 9 years
      Do you want to insert the HTML content of an action to a string variable? Or simply render an ActionResult inside another View?
    • user1620696
      user1620696 almost 9 years
      @FabioLuz I want to render the view and put the rendered HTML code inside a string variable.
    • tugberk
      tugberk almost 9 years
      If you want to do this while you are under MVC 6, it should be fairly straight forward. It's just a matter of getting the right dependency to rander the razor view. However, if you are outside of it, here is an example: github.com/tugberkugurlu/RazorOnConsole/blob/… dig in to see how Templater.Run is implemented.
    • AndroidDude123
      AndroidDude123 almost 9 years
      @tugberk that link is great, thanks! I'm not the OP, but your repo was incredibly helpful.
  • Matt DeKrey
    Matt DeKrey almost 9 years
    Unfortunately, the ViewEngines class also does not exist with asp.net-5.
  • Matt DeKrey
    Matt DeKrey about 8 years
    Glad to help! And thanks for noting it still works - I hadn't had to go back and change it, so hadn't added that note to my answer.
  • Shockwaver
    Shockwaver over 7 years
    Not seeing how you get those injected objects and also the signature of the method is incoherent with the way you call it...
  • Shockwaver
    Shockwaver over 7 years
    @MattDeKrey But it does in v4 (Not the OP request, I know)! Aaand this is absolutely the way to go for that version! Nice one, saved my day, no issues with any of the html helpers used with razor. THANK YOU
  • Seth
    Seth over 6 years
    @Shockwaver - just in case anyone wonders about this, it's just dependency injection (DI). The service dependencies are generally parameters to the constructor of the class and the DI container works out where to get them. With regards to the signature inconsistency, Matt probably wrote the original method inside a controller that has an ActionContext property so you can just change to a capital A and start testing the code from within a controller.