我在單獨的類庫中使用編譯的Razor視圖作爲MVC3的一種插件系統。MVC3 - 編譯的剃刀視圖找不到_ViewStart
我已經按照Chris Van De Steed here的指導進行了操作,只是主要關於添加引用的部分,因爲我在運行時加載了我的程序集。
因爲我在運行時加載程序集,所以我沒有在BoC庫中使用VirtualPathProviderViewEngine,而是實現了基於RazorViewEngine的自己的ViewEngine。它通過在CreateView中重寫viewPath來插入適當的名稱空間,以便解析視圖。
到目前爲止這麼好...我可以加載不同的模塊,如果他們的控制器共享相同的名稱,他們的控制器不會發生衝突。
我現在唯一的問題是,對於已編譯的視圖,_ViewStart不會被調用。 _ViewStart適用於主機MVC3項目中的視圖,但對於從插件程序集加載的任何視圖,都不會找到它。
我有一個路徑設定是這樣的: -
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));
當從插件程序集(在本例中爲「accounts」)加載視圖時,視圖被找到並顯示OK。但隨後它會在這些位置的_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
但它不看〜/查看/共享/ _ViewStart.cshtml文件的生活在那裏。
我試着改變我的ViewEngine(AreaMasterLocationFormats,AreaPartialViewLocationFormats,AreaViewLocationFormats,MasterLocationFormats,PartialViewLocationFormats和ViewLocationFormats)中的所有位置格式,但它們都沒有改變。
我環顧四周,似乎System.Web.WebPages.StartPage.GetStartPage負責查找並返回視圖中的起始頁面,但我找不到任何有關如何控制它的外觀的信息。
我已經試過移動_ViewStart.cshtml到〜/ _ViewStart.cshtml(它看起來的地方之一),但是我立刻得到: -
Unable to cast object of type 'ASP._Page__ViewStart_cshtml' to type 'System.Web.WebPages.StartPage'.
它根據我讀過,是因爲_ViewStart需要生活在/ Views
我可以修改MVC在哪裏查找_ViewStart嗎?
的中行庫實現它自己的iView,並要求如下: -
startPage = this.StartPageLookup(page, VirtualPathFactoryManagerViewEngine.ViewStartFileName, this.ViewStartFileExtensions);
但在這種情況下ViewStartFileName只是「_ViewStart」和ViewStartFileExtensions只是CSHTML和vbhtml ......沒有什麼會控制在何處MVC應該搜索文件。
我照你的建議做了,並創建了我自己的從RazorView繼承的「PluginRazorView」。 我不得不按照你的建議重寫RenderView,我試圖複製MVC GetStartPage方法所做的事情,只是添加我自己的邏輯來搜索額外的路徑,但是它是內部和反射的雷區,所以我只是一起黑客攻擊證明它的工作原理,我將不得不在晚些時候清理它。 有趣的是,他們在這裏使用了一個委託......似乎可以使用不同的搜索方法,但是沒有辦法指定它們。 非常感謝您的幫助。 – Aleks 2012-02-09 11:39:11
是的,這也是我的想法。就像你說的,他們使用一個委託來允許改變查找方法,但是然後聲明它是'internal',所以它只是Mvc命名空間,它實際上可以改變它... – JimmiTh 2012-02-09 13:50:48