ASP.NET MVC 修改視圖的默認路徑


本章將和大家分享如何在ASP.NET MVC中修改視圖的默認路徑。在此之前,首先我們要搞懂MVC它是怎么搜索視圖的。

先來看下Demo的目錄結構:

本Demo的Web項目為ASP.NET Web 應用程序(目標框架為.NET Framework 4.5) MVC項目。  

了解MVC的人應該都知道,在Action中如果要返回一個頁面,那我們一般的做法都是去調用View方法,如下所示:

接下來我們就通過反編譯工具來看一下這個View方法里面到底都做了啥:

可以看到它最后返回的是 ViewResult 對象,我們繼續通過反編譯工具來看一下這個 ViewResult 類:

可以發現,它是從 base.ViewEngineCollection 中找默認視圖的,下面我們繼續通過反編譯工具找到 base.ViewEngineCollection ,如下所示:

可以看到,其實它返回的就是一個 ViewEngineCollection 視圖引擎集合,並且它的取值來自 ViewEngines.Engines ,我們點擊 Engines 往里找:

繼續點擊 _engines 往里找:

找到最后我們可以發現,其實 ViewEngines.Engines 里面存放的就是 new WebFormViewEngine() 和 new RazorViewEngine() 。

我們通過反編譯工具找到 RazorViewEngine 這個類,如下所示:

using System;

namespace System.Web.Mvc
{
    /// <summary>Represents a view engine that is used to render a Web page that uses the ASP.NET Razor syntax.</summary>
    public class RazorViewEngine : BuildManagerViewEngine
    {
        internal static readonly string ViewStartFileName = "_ViewStart";

        /// <summary>Initializes a new instance of the <see cref="T:System.Web.Mvc.RazorViewEngine" /> class.</summary>
        public RazorViewEngine() : this(null)
        {
        }

        /// <summary>Initializes a new instance of the <see cref="T:System.Web.Mvc.RazorViewEngine" /> class using the view page activator.</summary>
        /// <param name="viewPageActivator">The view page activator.</param>
        public RazorViewEngine(IViewPageActivator viewPageActivator) : base(viewPageActivator)
        {
            base.AreaViewLocationFormats = new string[]
            {
                "~/Areas/{2}/Views/{1}/{0}.cshtml",
                "~/Areas/{2}/Views/{1}/{0}.vbhtml",
                "~/Areas/{2}/Views/Shared/{0}.cshtml",
                "~/Areas/{2}/Views/Shared/{0}.vbhtml"
            };
            base.AreaMasterLocationFormats = new string[]
            {
                "~/Areas/{2}/Views/{1}/{0}.cshtml",
                "~/Areas/{2}/Views/{1}/{0}.vbhtml",
                "~/Areas/{2}/Views/Shared/{0}.cshtml",
                "~/Areas/{2}/Views/Shared/{0}.vbhtml"
            };
            base.AreaPartialViewLocationFormats = new string[]
            {
                "~/Areas/{2}/Views/{1}/{0}.cshtml",
                "~/Areas/{2}/Views/{1}/{0}.vbhtml",
                "~/Areas/{2}/Views/Shared/{0}.cshtml",
                "~/Areas/{2}/Views/Shared/{0}.vbhtml"
            };
            base.ViewLocationFormats = new string[]
            {
                "~/Views/{1}/{0}.cshtml",
                "~/Views/{1}/{0}.vbhtml",
                "~/Views/Shared/{0}.cshtml",
                "~/Views/Shared/{0}.vbhtml"
            };
            base.MasterLocationFormats = new string[]
            {
                "~/Views/{1}/{0}.cshtml",
                "~/Views/{1}/{0}.vbhtml",
                "~/Views/Shared/{0}.cshtml",
                "~/Views/Shared/{0}.vbhtml"
            };
            base.PartialViewLocationFormats = new string[]
            {
                "~/Views/{1}/{0}.cshtml",
                "~/Views/{1}/{0}.vbhtml",
                "~/Views/Shared/{0}.cshtml",
                "~/Views/Shared/{0}.vbhtml"
            };
            base.FileExtensions = new string[]
            {
                "cshtml",
                "vbhtml"
            };
        }

        /// <summary>Creates a partial view using the specified controller context and partial path.</summary>
        /// <returns>The partial view.</returns>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="partialPath">The path to the partial view.</param>
        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
        {
            return new RazorView(controllerContext, partialPath, null, false, base.FileExtensions, base.ViewPageActivator)
            {
                DisplayModeProvider = base.DisplayModeProvider
            };
        }

        /// <summary>Creates a view by using the specified controller context and the paths of the view and master view.</summary>
        /// <returns>The view.</returns>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="viewPath">The path to the view.</param>
        /// <param name="masterPath">The path to the master view.</param>
        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
        {
            return new RazorView(controllerContext, viewPath, masterPath, true, base.FileExtensions, base.ViewPageActivator)
            {
                DisplayModeProvider = base.DisplayModeProvider
            };
        }
    }
}

你會驚奇的發現,上面描述的路徑就是我們MVC默認的視圖路徑。既然如此,那我們大概知道了,將來如果要做一些擴展(例如:修改MVC默認的視圖路徑),就可以從這個類入手。

話不多說,下面我們就重點來看下如何修改MVC默認的視圖路徑?

我們先來驗證下 ViewEngines.Engines 里面存放的到底是不是只有 new WebFormViewEngine() 和 new RazorViewEngine() ,如下所示:

通過調試 Global.asax 中 Application_Start 方法,我們可以發現 ViewEngines.Engines 里面存的確實只有 new WebFormViewEngine() 和 new RazorViewEngine() ,那么下面我們就可以大膽的去擴展了。

首先自定義一個Razor視圖引擎,如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace ViewEngineExtend.ViewEngineExtend
{
    /// <summary>
    /// 自定義Razor視圖引擎
    /// </summary>
    public class CustomRazorViewEngine : RazorViewEngine
    {
        #region 構造函數

        public CustomRazorViewEngine()
            : this(null)
        {

        }

        public CustomRazorViewEngine(IViewPageActivator viewPageActivator)
            : base(viewPageActivator)
        {

        }

        #endregion 構造函數

        public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
        {
            if (controllerContext.HttpContext.Request.UserAgent.Contains("Chrome"))
            {
                this.SetTheme("Chrome");
            }
            else
            {
                this.SetTheme(""); //一定得有,因為只有一個Engines實例
            }

            return base.FindView(controllerContext, viewName, masterName, useCache);
        }

        public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
        {
            if (controllerContext.HttpContext.Request.UserAgent.Contains("Chrome"))
            {
                this.SetTheme("Chrome");
            }
            else
            {
                this.SetTheme(""); //一定得有,因為只有一個Engines實例
            }

            return base.FindPartialView(controllerContext, partialViewName, useCache);
        }

        /// <summary>
        /// 設置主題(修改視圖的默認路徑)
        /// </summary>
        /// <param name="browser">瀏覽器</param>
        void SetTheme(string browser)
        {
            if (!string.IsNullOrEmpty(browser) && browser.Contains("Chrome"))
            {
                base.AreaViewLocationFormats = new string[]
                {
                    "~/Areas/{2}/ChromeViews/{1}/{0}.cshtml",
                    "~/Areas/{2}/ChromeViews/{1}/{0}.vbhtml",
                    "~/Areas/{2}/ChromeViews/Shared/{0}.cshtml",
                    "~/Areas/{2}/ChromeViews/Shared/{0}.vbhtml"
                };
                base.AreaMasterLocationFormats = new string[]
                {
                    "~/Areas/{2}/ChromeViews/{1}/{0}.cshtml",
                    "~/Areas/{2}/ChromeViews/{1}/{0}.vbhtml",
                    "~/Areas/{2}/ChromeViews/Shared/{0}.cshtml",
                    "~/Areas/{2}/ChromeViews/Shared/{0}.vbhtml"
                };
                base.AreaPartialViewLocationFormats = new string[]
                {
                    "~/Areas/{2}/ChromeViews/{1}/{0}.cshtml",
                    "~/Areas/{2}/ChromeViews/{1}/{0}.vbhtml",
                    "~/Areas/{2}/ChromeViews/Shared/{0}.cshtml",
                    "~/Areas/{2}/ChromeViews/Shared/{0}.vbhtml"
                };
                base.ViewLocationFormats = new string[]
                {
                    "~/ChromeViews/{1}/{0}.cshtml",
                    "~/ChromeViews/{1}/{0}.vbhtml",
                    "~/ChromeViews/Shared/{0}.cshtml",
                    "~/ChromeViews/Shared/{0}.vbhtml"
                };
                base.MasterLocationFormats = new string[]
                {
                    "~/ChromeViews/{1}/{0}.cshtml",
                    "~/ChromeViews/{1}/{0}.vbhtml",
                    "~/ChromeViews/Shared/{0}.cshtml",
                    "~/ChromeViews/Shared/{0}.vbhtml"
                };
                base.PartialViewLocationFormats = new string[]
                {
                    "~/ChromeViews/{1}/{0}.cshtml",
                    "~/ChromeViews/{1}/{0}.vbhtml",
                    "~/ChromeViews/Shared/{0}.cshtml",
                    "~/ChromeViews/Shared/{0}.vbhtml"
                };
            }
            else
            {
                base.AreaViewLocationFormats = new string[]
                {
                    "~/Areas/{2}/Views/{1}/{0}.cshtml",
                    "~/Areas/{2}/Views/{1}/{0}.vbhtml",
                    "~/Areas/{2}/Views/Shared/{0}.cshtml",
                    "~/Areas/{2}/Views/Shared/{0}.vbhtml"
                };
                base.AreaMasterLocationFormats = new string[]
                {
                    "~/Areas/{2}/Views/{1}/{0}.cshtml",
                    "~/Areas/{2}/Views/{1}/{0}.vbhtml",
                    "~/Areas/{2}/Views/Shared/{0}.cshtml",
                    "~/Areas/{2}/Views/Shared/{0}.vbhtml"
                };
                base.AreaPartialViewLocationFormats = new string[]
                {
                    "~/Areas/{2}/Views/{1}/{0}.cshtml",
                    "~/Areas/{2}/Views/{1}/{0}.vbhtml",
                    "~/Areas/{2}/Views/Shared/{0}.cshtml",
                    "~/Areas/{2}/Views/Shared/{0}.vbhtml"
                };
                base.ViewLocationFormats = new string[]
                {
                    "~/Views/{1}/{0}.cshtml",
                    "~/Views/{1}/{0}.vbhtml",
                    "~/Views/Shared/{0}.cshtml",
                    "~/Views/Shared/{0}.vbhtml"
                };
                base.MasterLocationFormats = new string[]
                {
                    "~/Views/{1}/{0}.cshtml",
                    "~/Views/{1}/{0}.vbhtml",
                    "~/Views/Shared/{0}.cshtml",
                    "~/Views/Shared/{0}.vbhtml"
                };
                base.PartialViewLocationFormats = new string[]
                {
                    "~/Views/{1}/{0}.cshtml",
                    "~/Views/{1}/{0}.vbhtml",
                    "~/Views/Shared/{0}.cshtml",
                    "~/Views/Shared/{0}.vbhtml"
                };
                //base.FileExtensions = new string[]
                //{
                //    "cshtml",
                //    "vbhtml"
                //};
            }
        }
    }
}

接着修改 Global.asax 中 Application_Start 方法,將默認的 RazorViewEngine 替換成自定義的 CustomRazorViewEngine ,如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

using ViewEngineExtend.ViewEngineExtend;

namespace ViewEngineExtend
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            //var viewEngineCollection = ViewEngines.Engines;
            ViewEngines.Engines.Clear();
            ViewEngines.Engines.Add(new WebFormViewEngine());
            ViewEngines.Engines.Add(new CustomRazorViewEngine()); //替換成自定義的Razor視圖引擎
        }
    }
}

此外,Demo中還准備了兩套視圖:

其中 ~/ChromeViews/Home/Index.cshtml 頁面代碼如下: 

@{
    ViewBag.Title = "Home Page";
}

<h1>This is ChromeViews/Home/Index</h1>

其中 ~/Views/Home/Index.cshtml 頁面代碼如下: 

@{
    ViewBag.Title = "Home Page";
}

<h1>This is Views/Home/Index</h1>

最后,我們分別使用 谷歌瀏覽器和IE瀏覽器 來訪問 /Home/Index 頁面,如下所示:

谷歌瀏覽器運行結果如下:

IE瀏覽器運行結果如下:

仔細觀察后你會發現同樣都是訪問 /Home/Index 頁面,但是這兩個瀏覽器的運行結果卻是不一樣的,說明我們的視圖引擎擴展成功了。 

至此本文就全部介紹完了,如果覺得對您有所啟發請記得點個贊哦!!! 

 

Demo源碼:

鏈接:https://pan.baidu.com/s/1TWVlsq98Sjt6qYOMXaTwCQ 
提取碼:3nm2

此文由博主精心撰寫轉載請保留此原文鏈接:https://www.cnblogs.com/xyh9039/p/15240321.html

版權聲明:如有雷同純屬巧合,如有侵權請及時聯系本人修改,謝謝!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM