11

約 3000 のビューを持つ ASP.NET MVC 4 アプリケーションがあります。この一連のビューを個別の DLL に分割し、RazorGenerator でコンパイルすることにしました。メインの _Layout.cshtml と関連ファイルのみをメインの MVC プロジェクトに保持します。

メイン MVC プロジェクトのマスター ビューと一緒に DLL から部分ビューを読み込むことはできません。詳細な説明は以下です。

すでに行われていること:

  1. ビューは正常に DLL にコンパイルされます (バイナリであることを確認しました)。

  2. PrecompiledMvc​​Engine オブジェクトは、Global.asax.cs の Application_Start で次のコードを使用して、ビューを含む各 DLL に対して作成および登録されます。

.

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);
}

機能しないもの:

ライブラリの 1 つ (Partial.cshtml など) で定義された部分ビューを使用して、メイン MVC プロジェクト (_Layout.cshtml など) で定義されたビューを読み込むことができません。コントローラーのアクションで次のコードを使用して、要求したビューを MVC フレームワークに伝えます。

var view = "~/Views/" + partialName + ".cshtml";    
return View(view, "~/Views/Shared/_Layout.cshtml", model);

エラー メッセージは次のように表示されます: ビュー '~/Views/Partial.cshtml' またはそのマスターが見つからないか、検索された場所をサポートするビュー エンジンがありません。次の場所が検索されました: ~/Views/Partial.cshtml ~/Views/Shared/_Layout.cshtml

次のいずれかを指定して、ビューを個別にロードしようとすると:

return View("~/Views/Shared/_Layout.cshtml", model);

また

return View(view, model);

、正しいビューが見つかりました。ただし、それらを一緒にロードする必要があります。メイン MVC プロジェクトに必要なすべての .cshtml ファイルがある場合、コードは機能します。

コンパイルされた DLL のビューには、コントローラー アクションで指定されたものと同じパスを持つ 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
        }
    }
}

要約すると、問題は、メイン MVC プロジェクトに格納されているマスター ビューを、別のプロジェクトで定義された部分コンパイル ビューで呼び出す方法です。

4

3 に答える 3

2

アプリの起動時に、アプリがこの行を呼び出すと...

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

外部ビューを含むアセンブリはまだ読み込まれていない可能性が高いため、ビュー エンジンとして含まれていません。AppDomain.CurrentDomain.GetAssemblies()起動時にロードされるすべてのアセンブリが含まれるため、実際には使用しないことをお勧めします。

解決策は、コンパイル済みビューを含む各プロジェクトにRazorGenerator.Mvc NuGet パッケージを追加することです。これにより、次のアプリ開始コードが同様の方法で追加されます...

[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);
        }
    }
}

これにより、現在のアセンブリ (ビュー アセンブリ) を使用してビュー エンジンが作成され、静的ViewEnginesコレクション (メイン MVC プロジェクトに含まれる) に追加されることに注意してください。

本番環境では、設定をオフにすることもお勧めしUsePhysicalViewsIfNewerます。これにより、パフォーマンスのオーバーヘッドが大幅に増加します。

于 2016-06-06T06:15:16.750 に答える