ASPを解読する.NET 5&MVC 6シリーズチュートリアル(16):カスタムViewファイル検索ロジック

3978 ワード

以前のMVC 5と以前のバージョンでは、Viewファイルのパスを制御するには、IViewEngineインターフェースのFindPartialViewまたはFindViewメソッドを書き換える必要があり、すべてのビューエンジンがこのIViewEngineインターフェース、例えばデフォルトRazorViewEngineに継承されている.しかし、新バージョンMVC 6では、ビューファイルへのパス方式が異なり、現在はRazorViewEngineと、新特性IViewLocationExpanderインタフェースの2つの方式がある.
RazorViewEngineによるViewパスの制御
新版RazorViewEngineでは、2つのダミー属性(AreaViewLocationFormatsおよびViewLocationFormats)が用意されており、書き換え制御に使用できます.FindPartialViewまたはFindViewメソッドを書き換える必要はありません.例は以下のとおりです.

public class ThemeViewEngine : RazorViewEngine
{
  public ThemeViewEngine(IRazorPageFactory pageFactory,
    IRazorViewFactory viewFactory,
    IViewLocationExpanderProvider viewLocationExpanderProvider,
    IViewLocationCache viewLocationCache)
    : base(pageFactory,
        viewFactory,
        viewLocationExpanderProvider,
        viewLocationCache)
  {
  }

  public override IEnumerable AreaViewLocationFormats
  {
    get
    {
      var value = new Random().Next(0, 1);
      var theme = value == 0 ? "Theme1" : "Theme2"; //        ,       
      return base.AreaViewLocationFormats.Select(f => f.Replace("/Views/", "/Views/" + theme + "/"));
    }
  }

  public override IEnumerable ViewLocationFormats
  {
    get
    {
      var value = new Random().Next(0, 1);
      var theme = value == 0 ? "Theme1" : "Theme2"; //        ,       
      return base.ViewLocationFormats.Select(f => f.Replace("/Views/", "/Views/" + theme + "/"));
    }
  }
}

次に、MVcOptionsのインスタンス属性ViewEnginesを変更することで、ビューエンジンの置換を完了します.コードは次のとおりです.

services.AddMvc().Configure(options =>
{
  options.ViewEngines.Clear();
  options.ViewEngines.Add(typeof(ThemeViewEngine));
});

これにより、ビューファイルを検索する際に、新しく登録されたThemeViewEngineの論理に従って実行される.
IViewLocationExpanderによるViewパスの制御
MVC 6では、マイクロソフトが別の新しい方法でViewファイルのパスを制御することを提供しています.それはIViewLocationExpanderインタフェースで、このインタフェースを実現することでカスタムロジックを実現し、関連するコンテキストオブジェクトを使用することもできます.例は次のとおりです.

public class ThemeViewLocationExpander : IViewLocationExpander
{
  public void PopulateValues(ViewLocationExpanderContext context)
  {
    var value = new Random().Next(0, 1);
    var theme = value == 0 ? "Theme1" : "Theme2";
    context.Values["theme"] = theme;
  }

  public virtual IEnumerable ExpandViewLocations(ViewLocationExpanderContext context,
                              IEnumerable viewLocations)
  {
    return viewLocations.Select(f => f.Replace("/Views/", "/Views/" + context.Values["theme"] + "/"));
  }
}

上記カスタムIViewLocationExpanderでは、2つの方法がそれぞれPopulateValuesおよびExpandViewLocationsPopulateValuesViewLocationExpanderContextコンテキストに応答のキー値ペアを追加して以降に使用することができ、このコンテキストイメージを利用してActionContextおよびHttpContextオブジェクトを検索し、これらのオブジェクトを利用して応答の判断操作を行うことができる.ExpandViewLocationsメソッドは、ビューキャッシュがない場合や、ビューキャッシュに対応するkeyのビューファイルが見つからない場合にのみ呼び出され、そのメソッド内でビューの位置を動的に戻すことができます.
最後に、Startup.csにおいて、RazorViewEngineOptionsインスタンスオブジェクトのViewLocationExpanders属性を修正することにより、登録目的を達成し、コードは以下の通りである.

services.Configure(options =>
{
  options.ViewLocationExpanders.Add(typeof(ThemViewLocationExpander));
});