asp.net-mvc-3 - MVC3 - 编译的 Razor View 找不到 _ViewStart

标签 asp.net-mvc-3 plugins razor

我在单独的类库中使用编译的 Razor View 作为 MVC3 的一种插件系统。

我遵循 Chris Van De Steed 的指南 here并且仅在添加引用的部分主要有所偏差,因为我在运行时加载程序集。

因为我在运行时加载程序集,所以我没有使用 BoC 库中的 VirtualPathProviderViewEngine,而是基于 RazorViewEngine 实现了我自己的 ViewEngine。它的工作原理是重写CreateView中的viewPath以插入适当的命名空间,以便可以解析 View 。

到目前为止一切顺利...我可以加载不同的模块,并且如果它们共享相同的名称,它们的 Controller 不会发生冲突。

我现在遇到的唯一问题是,对于编译 View ,未调用 _ViewStart。 _ViewStart 适用于主机 MVC3 项目中的 View ,但对于从插件程序集加载的任何 View ,找不到它。

我有这样的路线设置:-

RouteTable.Routes.MapRoute(
    string.Format("Plugin{0}Route", pluginName),
    string.Format(@"Plugin/{0}/{{controller}}/{{action}}", pluginName),
    new { },
    new string[] { string.Format("{0}.Controllers", pluginName) });

ViewEngine 看起来像这样:-

public class PluginRazorViewEngine : RazorViewEngine
{
    public PluginRazorViewEngine() : base()
    {
        ViewLocationFormats = new[]
        {
            "~/Plugin/%1/Views/{1}/{0}.cshtml",
            "~/Plugin/%1/Views/{1}/{0}.vbhtml",
            "~/Plugin/%1/Views/Shared/{0}.cshtml",
            "~/Plugin/%1/Views/Shared/{0}.vbhtml",
            "~/Views/{1}/{0}.cshtml",
            "~/Views/{1}/{0}.vbhtml",
            "~/Views/Shared/{0}.cshtml",
            "~/Views/Shared/{0}.vbhtml"
        };

(%1 被替换为程序集的名称)

并且该程序集已在 BoC 库中注册,如下所示:-

BoC.Web.Mvc.PrecompiledViews.ApplicationPartRegistry.Register(assembly, string.Format("/Plugin/{0}/", pluginName));

当从插件程序集(在本例中为“帐户”)加载 View 时,会找到该 View 并正常显示。但随后它会在这些位置查找 _ViewStart:-

~/plugin/accounts/views/invoice/_viewstart.cshtml
~/plugin/accounts/views/invoice/_viewstart.vbhtml
~/plugin/accounts/views/_viewstart.cshtml
~/plugin/accounts/views/_viewstart.vbhtml
~/plugin/accounts/_viewstart.cshtml
~/plugin/accounts/_viewstart.vbhtml
~/plugin/_viewstart.cshtml
~/plugin/_viewstart.vbhtml
~/_viewstart.cshtml
~/_viewstart.vbhtml

但它不会在文件所在的 ~/Views/Shared/_ViewStart.cshtml 中查找。

我尝试更改 ViewEngine 中的所有位置格式(AreaMasterLocationFormats、AreaPartialViewLocationFormats、AreaViewLocationFormats、MasterLocationFormats、PartialViewLocationFormats 和 ViewLocationFormats),但似乎都没有效果。

我环顾四周,似乎 System.Web.WebPages.StartPage.GetStartPage负责在 View 中查找并返回起始页,但我找不到任何有关如何控制其外观的信息。

我尝试将 _ViewStart.cshtml 移动到 ~/_ViewStart.cshtml (它看起来的地方之一),但我立即得到:-

Unable to cast object of type 'ASP._Page__ViewStart_cshtml' to type 'System.Web.WebPages.StartPage'.

根据我读到的内容,是因为 _ViewStart 需要位于/Views 下

我可以修改 MVC 查找 _ViewStart 的位置吗?

BoC 库实现它自己的 IView,并调用以下内容:-

startPage = this.StartPageLookup(page, VirtualPathFactoryManagerViewEngine.ViewStartFileName, this.ViewStartFileExtensions);

但在本例中,ViewStartFileName 只是“_ViewStart”,ViewStartFileExtensions 只是 cshtml 和 vbhtml...没有任何内容可以控制 MVC 应在何处搜索文件。

最佳答案

一个想法...(例如,还没有尝试过。它会起作用吗?不知道)

也许看看继承 RazorView (或者完全替换它,考虑到 - 正如我们将看到的 - 您将重写作为类大部分的一个方法)。

RazorView是哪里StartPage.GetStartPage通过将其分配给 StartPageLookup 来引入属性:

// In RazorView constructor:
StartPageLookup = StartPage.GetStartPage;

不幸的是,该委托(delegate)属性是内部的,因此您不能在派生类的构造函数中覆盖它。但是,您可以覆盖 RazorView.RenderView ,这就是它的使用位置(MVC3 源代码,删除了很多行,我添加了换行符):

protected override void RenderView(ViewContext viewContext, TextWriter writer, 
   object instance) 
{
  // [SNIP]

  WebPageRenderingBase startPage = null;
  if (RunViewStartPages) {
     // HERE IT IS:
     startPage = StartPageLookup(
        webViewPage, 
        RazorViewEngine.ViewStartFileName, 
        ViewStartFileExtensions
     );
  }
  webViewPage.ExecutePageHierarchy(
     new WebPageContext(
        context: viewContext.HttpContext, 
        page: null, 
        model: null),
     writer, startPage);
}

将 StartPageLookup 调用替换为您自己的查找,然后替换 CreateView 的结果和CreatePartialView在你的PluginRazorViewEngine与您的新PluginRazorView类。

关于asp.net-mvc-3 - MVC3 - 编译的 Razor View 找不到 _ViewStart,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9191498/

相关文章:

asp.net-mvc-3 - 那些类型的服务是否应该注入(inject)基类中? (与静态类相比)

javascript - 将值从 MVC Controller 传递到 javascript 代码

asp.net-mvc-3 - Entity Framework 检测到有冲突的更改。尝试插入多个具有相同键的实体时可能会发生这种情况

java - 将项目添加到插件

javascript - 表单不是动态创建的

razor MVC EF 如何根据模型条件显示和隐藏 div

asp.net-mvc - MVC3 站点生成器应用程序设计

asp.net - 样式嵌套在另一种样式的 asp.net View 中,但不确定如何嵌套

javascript - 从多个表单中选择特定元素

plugins - Notepad++插件同时编辑开始和结束的html标签