解讀ASP.NET 5 & MVC6系列(16):自定義View檢視檔案查詢邏輯
之前MVC5和之前的版本中,我們要想對View檔案的路徑進行控制的話,則必須要對IViewEngine
介面的FindPartialView
或FindView
方法進行重寫,所有的檢視引擎都繼承於該IViewEngine
介面,比如預設的RazorViewEngine
。但新版本MVC6中,對檢視檔案的路徑方式卻不太一樣了,目前有兩種方式,一種是通過RazorViewEngine
,另外一種是通過新特性IViewLocationExpander
介面。
通過RazorViewEngine來控制View路徑
在新版的RazorViewEngine
中,該類提供了兩個虛屬性(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<string> 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<string> 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<MvcOptions>(options =>
{
options.ViewEngines.Clear();
options.ViewEngines.Add(typeof(ThemeViewEngine));
});
這樣,系統在查詢檢視檔案的時候,就會按照新註冊的ThemeViewEngine
的邏輯來執行。
通過IViewLocationExpander來控制View路徑
在MVC6中,微軟還提供了另外一種新的方式來控制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<string> ExpandViewLocations(ViewLocationExpanderContext context,
IEnumerable<string> viewLocations)
{
return viewLocations.Select(f => f.Replace("/Views/", "/Views/" + context.Values["theme"] + "/"));
}
}
在上述自定義的IViewLocationExpander
中,實現了2個方法分別是PopulateValues
和ExpandViewLocations
,PopulateValues
方法可以讓我們想ViewLocationExpanderContext
上下文中新增響應的鍵值對以便後續使用,通過,我們可以利用通過該上下文物件,來查詢ActionContext
和HttpContext
物件,以便利用這些物件做響應的判斷操作;而ExpandViewLocations
方法,只會在沒有View快取或在View快取裡找不到對應key的View檔案時才會呼叫該方法,在該方法內,我們可以動態返回檢視的位置。
最後,我們在Startup.cs
裡通過修改RazorViewEngineOptions
例項物件的ViewLocationExpanders
屬性,來實現註冊目的,程式碼如下:
services.Configure<RazorViewEngineOptions>(options =>
{
options.ViewLocationExpanders.Add(typeof(ThemViewLocationExpander));
});