Razor 发电机 : how to use view compiled in a library as the partial view for master defined in main mvc project

标签 razor asp.net-mvc-4 viewengine razorgenerator

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

我们无法从 DLL 中加载部分 View 以及主 MVC 项目中的主 View 。详细说明如下。

已经完成的:

  • View 成功编译成 DLL(我已经确认它们在二进制文件中)
  • 使用 Global.asax.cs 中 Application_Start 中的以下代码为每个包含 View 的 DLL 创建和注册 PrecompiledMvc​​Engine 对象:

  • .
    foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
    {
        // ...
        // some code determining whether we've got an assembly with views
        // ...
    
        var engine = new PrecompiledMvcEngine(assembly);
        engine.UsePhysicalViewsIfNewer = true;
    
        ViewEngines.Engines.Insert(0, engine);
    
        // StartPage lookups are done by WebPages. 
        VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);
    }
    

    什么不起作用:

    我无法加载在主 MVC 项目(例如 _Layout.cshtml)中定义的 View 以及在其中一个库(例如 Partial.cshtml)中定义的部分 View 。我在 Controller 的操作中使用以下代码来告诉 MVC 框架我请求哪个 View :
    var view = "~/Views/" + partialName + ".cshtml";    
    return View(view, "~/Views/Shared/_Layout.cshtml", model);
    

    错误消息说:
    未找到 View “~/Views/Partial.cshtml”或其母版,或者没有 View 引擎支持搜索的位置。搜索了以下位置:
    ~/Views/Partial.cshtml
    ~/Views/Shared/_Layout.cshtml

    当我尝试通过指定以下任一项来单独加载 View 时:
    return View("~/Views/Shared/_Layout.cshtml", model);
    

    或者
    return View(view, model);
    

    ,找到了正确的观点。但是我需要将它们一起加载。当我在主 MVC 项目中拥有所有必需的 .cshtml 文件时,代码工作。

    请注意,已编译 DLL 中的 View 具有与 Controller 操作中指定的路径相同的 PageVirtualPathAttribute,例如:
    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
            }
        }
    }
    

    综上所述,问题是如何用另一个项目中定义的部分编译 View 调用存储在主MVC项目中的主 View ?

    最佳答案

    在应用程序启动时,当您的应用程序调用此行时...

    foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
    

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

    解决方法是添加RazorGenerator.Mvc NuGet 打包到每个包含编译 View 的项目。这将以与您类似的方式添加以下应用程序启动代码...
    [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);
            }
        }
    }
    

    请注意这如何使用当前程序集(您的 View 程序集)创建 View 引擎并将其添加到静态 ViewEngines集合(包含在主 MVC 项目中)。

    一旦投入生产,我还建议关闭 UsePhysicalViewsIfNewer设置,这增加了显着的性能开销。

    关于 Razor 发电机 : how to use view compiled in a library as the partial view for master defined in main mvc project,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13527354/

    相关文章:

    c# - Nustache View 引擎 ArrayTypeMismatchException

    asp.net-mvc - 当在 View 引擎中指定位置时,为什么在 viewstart 文件中需要布局的完整路径?

    asp.net - 在 Web 表单应用程序中使用 Razor View 作为电子邮件模板

    jquery - 通过平滑滚动重定向到不同页面上的 div?

    asp.net-mvc-4 - jQuery 不显眼的验证不起作用

    c# - ASP.Net MVC/Web API 自定义动态包在生产中工作但不在开发中

    c# - MVC 从 Web 服务解析 XML

    java - Java 中的 View 引擎有哪些选项?

    asp.net-mvc-3 - MVC3 Razor 编辑器/显示模板和泛型

    asp.net-mvc - 是否可以在 Razor 中将一种形式嵌套在另一种形式中?