2012-02-08 5 views
5

私は別のクラスライブラリでコンパイル済みの剃刀ビューを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と表示されます。

~/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に見ていない - :しかし、それは_ViewStartのためのこれらの場所を検索します。

私は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'. 

私が読んだによると、どちらが/ Viewの下に_ViewStartを置く必要があるため、

MVCが_ViewStartを探す場所を変更できますか?

のBOCライブラリが、それは自分のIViewのだ実装していないし、次の呼び出します -

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

しかし、この場合にはViewStartFileNameはちょうど「_ViewStart」であるとViewStartFileExtensionsがちょうどCSHTMLとvbhtmlですが...制御します何もMVCはファイルを検索する必要があります。それは無いように思えるMVCは_ViewStartを検索する場所、あなたが変更することはできませんので

答えて

1

アイデアは...(のように、それを試していない、それは動作しませんも考えて。?)

はたぶんRazorViewから継承(またはそれを完全に置き換え、考慮を見て - 私たちはよと〜を参照してくださいクラスの大部分である1つのメソッドを書き直すことになります)。

RazorViewStartPage.GetStartPageStartPageLookupプロパティに割り当てる方法によって導入された場所です:あなたは自分の派生クラスのコンストラクタで、それを上書きすることはできませんので

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

残念ながら、そのデリゲートプロパティは、内部にあります。あなたは、しかし、それはを使用(MVC3のソースコードは、削除された行の多く、私が追加した改行)だところである、RazorView.RenderViewを上書きすることができる場合があります

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独自に呼び出すことを交換してください検索の結果、PluginRazorViewEngineCreateViewCreatePartialViewの結果を新しいPluginRazorViewクラスに置き換えます。

+0

RazorViewから継承した独自の「PluginRazorView」を提案して作成しました。 RenderViewをオーバーライドする必要がありましたが、MVC GetStartPageメソッドが何を複製して、追加のパスを検索するための独自のロジックを追加しようとしましたが、内部と反射の地雷ですので、それが動作することを証明し、私は後でそれを掃除する必要があります。 ここではデリゲートを使用しているのは面白いです...さまざまな検索方法を使用できるようですが、指定する方法はありません。 多くのご協力ありがとうございます。 – Aleks

+0

ええ、それは私があまりにも思ったことです。あなたが言うように、彼らは参照メソッドを変更することを許可するために代理人を使用していますが、次にそれを 'internal'宣言するので、それは実際にそれを変更できるMvc名前空間だけです... – JimmiTh

1

、自分の質問に答えるために... ... System.Web.WebPages.StartPageのソースを見てみると

。 GetStartPage(私はhereから得ました)私はそれが呼び出しページからルートまでのパスをたどるだけで、この動作を制御する方法はないように見えます(つまり、 System.Web.WebPages.StartPage)

通常の状況(つまり、標準のMVC3レイアウト)はOKです。すべてのビューは/ Viewsの下にあります。また、_StartStartファイルもメインであり、GetStartPageが到達したときに評価されます。それ。

私が基本的に行ったことは、ビューを/ Viewsフォルダ階層から移動することでこの機能を無効にすることです。

これは、_ViewStartファイルを見つけられる場所に移動することができます(どのような種類のものであれ、私のすべてのプラグインで共通の_ViewStartを持つことを目的としています)か、/View/Shared/_ViewStart(これはすぐにわかりません)の正しいファイルに、その階層内の_ViewStartの要求をリダイレクトします。面白いのは何

はMVC3コードは「型のオブジェクトをキャストすることができません、その結果、動作しません、私が読んだものに基づいて/、に_ViewStartを探すということです 『ASP。ページ _ViewStart_cshtml』へ'System.Web.WebPages.StartPage' "というエラーが出ます(これは、デフォルトの/web.configが/Views/web.configとは異なり、ファイルを正しく解析するために必要なものがないからです)

関連する問題