Razor生成器:如何使用库中编译的视图作为主mvc项目中定义的主视图的部分视图

Razor生成器:如何使用库中编译的视图作为主mvc项目中定义的主视图的部分视图,razor,asp.net-mvc-4,viewengine,razorgenerator,Razor,Asp.net Mvc 4,Viewengine,Razorgenerator,我们有一个ASP.NETMVC4应用程序,其中包含大约3000个视图。我们决定将这组视图拆分为单独的DLL,并使用RazorGenerator进行编译。我们只在主MVC项目中保留main _Layout.cshtml和相关文件 我们不能在主MVC项目中从DLL加载部分视图和主视图。详细说明如下 已经完成的操作: 视图成功编译成DLL(我已经确认它们是二进制的) 使用Global.asax.cs中的应用程序_Start中的以下代码,为每个包含视图的DLL创建并注册预编译MVCEngine对象:

我们有一个ASP.NETMVC4应用程序,其中包含大约3000个视图。我们决定将这组视图拆分为单独的DLL,并使用RazorGenerator进行编译。我们只在主MVC项目中保留main _Layout.cshtml和相关文件

我们不能在主MVC项目中从DLL加载部分视图和主视图。详细说明如下

已经完成的操作:

  • 视图成功编译成DLL(我已经确认它们是二进制的)

  • 使用Global.asax.cs中的应用程序_Start中的以下代码,为每个包含视图的DLL创建并注册预编译MVCEngine对象:

  • 什么不起作用:

    我无法加载主MVC项目(比如_Layout.cshtml)中定义的视图,其中一个库(比如partial.cshtml)中定义了部分视图。我在controller的操作中使用以下代码告诉MVC框架我请求的视图:

    var view = "~/Views/" + partialName + ".cshtml";    
    return View(view, "~/Views/Shared/_Layout.cshtml", model);
    
    错误消息显示: 找不到视图“~/Views/Partial.cshtml”或其主视图,或者没有视图引擎支持搜索的位置。搜索了以下地点: ~/Views/Partial.cshtml ~/Views/Shared/\u Layout.cshtml

    当我试图通过指定以下任一项单独加载视图时:

    return View("~/Views/Shared/_Layout.cshtml", model);
    

    ,则会找到正确的视图。但是我需要把它们装在一起。当我在主MVC项目中拥有所有必需的.cshtml文件时,代码就可以工作了

    请注意,已编译DLL中的视图具有与控制器操作中指定的路径相同的PageVirtualPath属性,例如:

    namespace SomeBaseNamespace.Views
    {
        [GeneratedCode("RazorGenerator", "1.5.0.0"), PageVirtualPath("~/Views/Partial.cshtml")]
        public class Partial : WebViewPage<PartialModel>
        {
            [CompilerGenerated]
            private static class <Execute>o__SiteContainer3
            {
                // logic
            }
    
            public override void Execute()
            {
                // logic
            }
        }
    }
    
    namespace SomeBaseNamespace.Views
    {
    [GeneratedCode(“RazorGenerator”,“1.5.0.0”),PageVirtualPath(“~/Views/Partial.cshtml”)]
    公共类部分:WebViewPage
    {
    [编译生成]
    私有静态类o__SiteContainer3
    {
    //逻辑
    }
    公共覆盖无效执行()
    {
    //逻辑
    }
    }
    }
    

    总而言之,问题是如何调用存储在主MVC项目中的主视图,以及在另一个项目中定义的部分编译视图?

    调用
    应用程序启动时,并非所有程序集都被加载。添加一个额外的处理程序:

    AppDomain.CurrentDomain.AssemblyLoad += (sender, args) => 
    {
        // ...
        // some code determining whether we've got an assembly with views
        // ...
    
        var engine = new PrecompiledMvcEngine(args.LoadedAssembly);
        engine.UsePhysicalViewsIfNewer = true;
    
        ViewEngines.Engines.Insert(0, engine);
    
        // StartPage lookups are done by WebPages. 
        VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);
    }
    
    术语

    BaseMvc-具有Razor生成的视图、控制器等
    ConsumerMvc-具有此项目的布局并参考BaseMvc

    总结

    在基本控制器中创建视图的传递。该视图使用一个布局,该布局通过BaseMvc中的_ViewStart.cshtml显示在ConsumerMvc中。对于我的情况,我有不同布局的项目,因此有“指针”布局视图。我认为这是一个有用的例子

    BaseMvc示例 我创建了一个
    区域
    ,以便设置默认布局

    /Areas/Components/controller/ShoppingController.cs

    public ActionResult Basket()
    {
        return View();
    }
    
    /Areas/Components/Views/Shopping/Basket.cshtml

    Welcome to the Basket!
    
    @{
        //-- NOTE: "Layout_Component.cshtml" do not exist in the BaseMVC project. I did not
        // experiment with having it in both projects. A tip if you do is to ensure both
        // the base and consumer _Layout_Component.cshtml files are both razor
        // generated to allow the razor generator to handle the overrride. See
        // my other SO answer linked below.
        Layout = "~/Views/Shared/_Layout_Component.cshtml";
    }
    
    @{
        Layout = "~/Views/Shared/_Layout_ConsumerMvc.cshtml";
    }
    @RenderBody()
    
    /Areas/Components/Views/_ViewStart.cshtml

    Welcome to the Basket!
    
    @{
        //-- NOTE: "Layout_Component.cshtml" do not exist in the BaseMVC project. I did not
        // experiment with having it in both projects. A tip if you do is to ensure both
        // the base and consumer _Layout_Component.cshtml files are both razor
        // generated to allow the razor generator to handle the overrride. See
        // my other SO answer linked below.
        Layout = "~/Views/Shared/_Layout_Component.cshtml";
    }
    
    @{
        Layout = "~/Views/Shared/_Layout_ConsumerMvc.cshtml";
    }
    @RenderBody()
    
    代码注释中引用的链接:

    ConsumerMvc示例 /Views/Shared/\u Layout\u Component.cshtml

    Welcome to the Basket!
    
    @{
        //-- NOTE: "Layout_Component.cshtml" do not exist in the BaseMVC project. I did not
        // experiment with having it in both projects. A tip if you do is to ensure both
        // the base and consumer _Layout_Component.cshtml files are both razor
        // generated to allow the razor generator to handle the overrride. See
        // my other SO answer linked below.
        Layout = "~/Views/Shared/_Layout_Component.cshtml";
    }
    
    @{
        Layout = "~/Views/Shared/_Layout_ConsumerMvc.cshtml";
    }
    @RenderBody()
    
    我的网址
    http://www.consumermvc.example.com/Components/Shopping/Basket

    在应用程序启动时,当您的应用程序调用此线路时

    foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
    
    包含外部视图的程序集可能尚未加载,因此不包括在视图引擎中。实际上,我建议不要使用
    AppDomain.CurrentDomain.GetAssemblies()
    ,因为这将包括启动时加载的所有程序集

    解决方案是将NuGet包添加到包含编译视图的每个项目中。这将以类似于您的方式添加以下应用程序启动代码

    [assembly: WebActivatorEx.PostApplicationStartMethod(typeof(SomeBaseNamespace.Views.RazorGeneratorMvcStart), "Start")]
    
    namespace SomeBaseNamespace.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);
            }
        }
    }
    
    请注意,这将如何使用当前部件(视图部件)创建视图引擎,并将其添加到静态
    ViewEngines
    集合(包含在主MVC项目中)


    投入生产后,我还建议关闭
    UsePhysicalViewsIfNewer
    设置,这会增加大量性能开销。

    您好,您能做到这一点吗?您有没有想过?我似乎遇到了完全相同的问题。这将添加所有加载的程序集作为视图引擎,这是不推荐的。对于包含在需要之前从未加载过的视图的程序集,这也不起作用。@TomBowers,你说得对,但这是他的问题使用的代码。最好有一个
    PrecompiledMvcEngine
    ,可以根据需要添加来自其他程序集的视图。不能对多个程序集使用PrecompiledMvcEngine。对于每个包含编译视图的独立程序集,您需要一个新引擎,如我的回答所示。