MVC 5渲染视图到字符串

wh1*_*p3r 22 asp.net-mvc asp.net-mvc-5

看来,用于将视图呈现为字符串的大多数代码在MVC 5中都不起作用.

我有最新的MVC 5.1.2模板,我试图将视图渲染成字符串.

    public static String RenderViewToString(ControllerContext context, String viewPath, object model = null)
    {
        context.Controller.ViewData.Model = model;
        using (var sw = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindView(context, viewPath, null);
            var viewContext = new ViewContext(context, viewResult.View, context.Controller.ViewData, context.Controller.TempData, sw);
            viewResult.View.Render(viewContext, sw);
            viewResult.ViewEngine.ReleaseView(context, viewResult.View);
            return sw.GetStringBuilder().ToString();
        }
    }
Run Code Online (Sandbox Code Playgroud)

嗯,它正在工作,但它的输出包含许多$标记而不是标记.我读过有关它的内容已在RC版本中修复,但这是旧闻.

问题看起来像这样

<$A$><h1></h1> 
<table</$A$><$B$> class=""</$B$><$C$>> <tbody</$C$><$D$></$D$><$E$>></tbody>
</table></$E$>
Run Code Online (Sandbox Code Playgroud)

我想问一下,如何在最新的MVC 5模板中将视图呈现为字符串?谢谢.

wh1*_*p3r 31

好吧,我似乎找到了解决方案.这个想法的作者是亚基尔庄园.

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();

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是假上下文和响应的一个技巧.

例:

String renderedHTML = RenderViewToString("Email", "MyHTMLView", myModel );
Run Code Online (Sandbox Code Playgroud)

我的文件MyHTMLView.cstml存储在Views/Email/MyHTMLView.cshtml中.电子邮件是虚假的控制器名称.


Alo*_*lok 6

以下是与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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是您从另一个控制器调用的方式

var modal = getModal(params);
return FakeController.RenderViewToString(controllerName, viewName, areaName, modal, this.Request.RequestContext);
Run Code Online (Sandbox Code Playgroud)

使用requestcontext,我们可以轻松地在fakecontroller中传递当前会话并呈现剃刀字符串。