RazorViewEngine.FindView找不到预编译的视图

oca*_*nal 4 asp.net asp.net-mvc precompiled razor razorgenerator

App.Web并且App.Views我的项目在一个解决方案中,我将我的视图放在App.Views中并使用RazorGenerator进行预编译.如果我用的话,它运作良好App.Web,

~/Views/Index.cshtml 是App.View中我的视图的虚拟路径

它可以在App.Web中成功呈现此视图

public ActionResult Index() {
  return View("~/Views/Index.cshtml");
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试时RenderViewToString,它会返回null.

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)

这就是它的全部,

FakeController.RenderViewToString("FakeName", "~/Views/Index.csthml", MessageModel);
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

这是在asp.net核心中讨论并可能解决的,但我正在使用asp.net mvc 5.

你能不能帮我弄清楚,为什么它不起作用?

Cod*_*ler 5

您正在尝试使用Razor View Engine获取预编译的视图.这是个错误.Razor引擎根据cshtml文件生成视图.但是,在预编译视图的情况下,cshtml文件已经被编译RazorGenerator为派生自的一组类System.Web.Mvc.WebViewPage.这些类覆盖了将html写入输出的方法Execute()(RazorGenerator基于输入cshtml 自动生成)TextWriter.原始视图文件(cshtml)不再需要,因此不会与应用程序一起部署.当您调用Razor尝试定位cshtml并基于它构建视图时,它应该返回null视图.

ASP.NET MVC支持多个视图引擎(实现的类System.Web.Mvc.IViewEngine).RazorViewEngine是其中之一.RazorGenerator.MvcNuGet包添加了自己的视图引擎(PrecompiledMvcEngine),它基于预编译视图.已注册的视图引擎存储在ViewEngines.Engines集合中.当您安装RazorGenerator.MvcNuGet包时,它会添加RazorGeneratorMvcStart注册实例的类PrecompiledMvcEngine:

[assembly: WebActivatorEx.PostApplicationStartMethod(typeof(App.Views.RazorGeneratorMvcStart), "Start")]

namespace App.Views {
    public static class RazorGeneratorMvcStart {
        public static void Start() {
            var engine = new PrecompiledMvcEngine(typeof(RazorGeneratorMvcStart).Assembly) {
                UsePhysicalViewsIfNewer = HttpContext.Current.Request.IsLocal
            };

            ViewEngines.Engines.Insert(0, engine);

            // StartPage lookups are done by WebPages. 
            VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您应该使用此实例PrecompiledMvcEngine而不是RazorViewEngine访问预编译视图.这是调整后的RenderViewToString方法代码:

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 viewEngine = ViewEngines.Engines.OfType<PrecompiledMvcEngine>().FirstOrDefault();
        if (viewEngine == null)
        {
            throw new InvalidOperationException("PrecompiledMvcEngine is not registered");
        }
        var viewResult = viewEngine.FindView(fakeControllerContext, viewName, "", false);
        var viewContext = new ViewContext(fakeControllerContext, viewResult.View, new ViewDataDictionary(viewData), new TempDataDictionary(), writer);
        viewResult.View.Render(viewContext, writer);
        return writer.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

一个重要的注意事项:您应该RazorGenerator.Mvc使用您的views(App.Views)将NuGet包安装到项目中,而不是安装到Web应用程序项目中,因为PrecompiledMvcEngine将当前程序集作为预编译视图的源.Aslo确保RazorGeneratorMvcStart没有添加到App.Web项目中.当我添加对RazorGenerator.Mvc.dll程序集的引用时,它发生在我身上.

GitHub上的示例项目