MVC 5 Render View to String
following is the solution that works with session and areas on MVC5.
public class FakeController : ControllerBase
{
protected override void ExecuteCore() { }
public static string RenderViewToString(string controllerName, string viewName,string areaName, object viewData,RequestContext rctx)
{
try
{
using (var writer = new StringWriter())
{
var routeData = new RouteData();
routeData.Values.Add("controller", controllerName);
routeData.Values.Add("Area", areaName);
routeData.DataTokens["area"] = areaName;
var fakeControllerContext = new ControllerContext(rctx, new FakeController());
//new ControllerContext(new HttpContextWrapper(new HttpContext(new HttpRequest(null, "http://google.com", null), new HttpResponse(null))), routeData, new FakeController());
fakeControllerContext.RouteData = routeData;
var razorViewEngine = new RazorViewEngine();
var razorViewResult = razorViewEngine.FindView(fakeControllerContext, viewName, "", false);
var viewContext = new ViewContext(fakeControllerContext, razorViewResult.View, new ViewDataDictionary(viewData), new TempDataDictionary(), writer);
razorViewResult.View.Render(viewContext, writer);
return writer.GetStringBuilder().ToString();
//use example
//String renderedHTML = RenderViewToString("Email", "MyHTMLView", myModel );
//where file MyHTMLView.cstml is stored in Views/Email/MyHTMLView.cshtml. Email is a fake controller name.
}
}
catch (Exception ex)
{
//do your exception handling here
}
}
}
here is how you call this from another controller
var modal = getModal(params);
return FakeController.RenderViewToString(controllerName, viewName, areaName, modal, this.Request.RequestContext);
using requestcontext we can easily pass current session in fakecontroller and render razor string.
Ok, seems I found a solution. Author of the idea is Yakir Manor.
class FakeController : ControllerBase
{
protected override void ExecuteCore() { }
public static string RenderViewToString(string controllerName, string viewName, object viewData)
{
using (var writer = new StringWriter())
{
var routeData = new RouteData();
routeData.Values.Add("controller", controllerName);
var fakeControllerContext = new ControllerContext(new HttpContextWrapper(new HttpContext(new HttpRequest(null, "http://google.com", null), new HttpResponse(null))), routeData, new FakeController());
var razorViewEngine = new RazorViewEngine();
var razorViewResult = razorViewEngine.FindView(fakeControllerContext, viewName, "", false);
var viewContext = new ViewContext(fakeControllerContext, razorViewResult.View, new ViewDataDictionary(viewData), new TempDataDictionary(), writer);
razorViewResult.View.Render(viewContext, writer);
return writer.ToString();
}
}
}
It's a trick with fake context and response.
Example:
String renderedHTML = RenderViewToString("Email", "MyHTMLView", myModel );
My file MyHTMLView.cshtml is stored in Views/Email/MyHTMLView.cshtml. Email is a fake controller name.