解讀ASP.NET 5 & MVC6系列(16):自定義View視圖文件查找邏輯

以前MVC5和以前的版本中,咱們要想對View文件的路徑進行控制的話,則必需要對IViewEngine接口的FindPartialViewFindView方法進行重寫,全部的視圖引擎都繼承於該IViewEngine接口,好比默認的RazorViewEngine。但新版本MVC6中,對視圖文件的路徑方式卻不太同樣了,目前有兩種方式,一種是經過RazorViewEngine,另一種是經過新特性IViewLocationExpander接口。html

經過RazorViewEngine來控制View路徑

在新版的RazorViewEngine中,該類提供了兩個虛屬性(AreaViewLocationFormatsViewLocationFormats),能夠用於重寫控制,而沒必要再對FindPartialViewFindView方法進行重寫,示例以下:緩存

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便可完成對視圖引擎的替換,代碼以下:iview

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

這樣,系統在查找視圖文件的時候,就會按照新註冊的ThemeViewEngine的邏輯來執行。dom

經過IViewLocationExpander來控制View路徑

在MVC6中,微軟還提供了另一種新的方式來控制View文件的路徑,那就是IViewLocationExpander接口,經過實現該接口便可實現自定義邏輯,而且也可使用相關的上下文對象。示例以下:ide

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個方法分別是PopulateValuesExpandViewLocationsPopulateValues方法可讓咱們想ViewLocationExpanderContext上下文中添加響應的鍵值對以便後續使用,經過,咱們能夠利用經過該上下文對象,來查找ActionContextHttpContext對象,以便利用這些對象作響應的判斷操做;而ExpandViewLocations方法,只會在沒有View緩存或在View緩存裏找不到對應key的View文件時纔會調用該方法,在該方法內,咱們能夠動態返回視圖的位置。code

最後,咱們在Startup.cs裏經過修改RazorViewEngineOptions實例對象的ViewLocationExpanders屬性,來實現註冊目的,代碼以下:orm

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

同步與推薦

本文已同步至目錄索引:解讀ASP.NET 5 & MVC6系列htm

相關文章
相關標籤/搜索