• 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

    版权声明:如有雷同纯属巧合,如有侵权请及时联系本人修改,谢谢!!!

  • 相关阅读:
    [python] defaultdict
    [VM workstation]VM workstation 中的虚拟机连不上网络
    [Docker] docker 基础学习笔记1(共6篇)
    [python] import curses
    servlet 产生随机验证码
    JSTL标签库 sql标签
    JSTLLearning
    Ajax实现联想(建议)功能
    HDU 1241
    Servlet实现文件上传
  • 原文地址:https://www.cnblogs.com/xyh9039/p/15240321.html
Copyright © 2020-2023  润新知