我在单独的类库中使用编译的 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/