• 定制属于你自己的ViewEngine(一套逻辑多套UI)


    ASP.NET MVC出来这么久了,心中却又很多的疑惑:为什么所有的View都要放在Views目录下? 为什么Shared文件夹下面的页面可以被共享? 为什么Page既可以是*.cshtml,也可以是*.aspx? 

    其实上面的几个问题归结起来都是视图引擎的功效。

    在传统的ASP.NET中,可能还没有ViewEngine的概念。因为在Web From里面,实现Page实现了IHttpHanlder的接口,所以Page既是响应的处理类,也是视图的渲染类。在ASP.NET MVC中,视图的概念被抽象了出来,试图引擎的概念也被抽象成了一个接口。

    首先来看一下IViewEngine接口的定义

    1 namespace System.Web.Mvc
    2 {
    3     public interface IViewEngine
    4     {
    5         ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache);
    6         ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache);
    7         void ReleaseView(ControllerContext controllerContext, IView view);
    8     }
    9 }

    总共3个函数,总结起来大概就是两个功能:Find & Release。

    默认情况下,ASP.NET MVC提供了两个视图引擎:WebFormViewEngine和RazorViewEngine

     1 namespace System.Web.Mvc
     2 {
     3     public static class ViewEngines
     4     {
     5         private static readonly ViewEngineCollection _engines = new ViewEngineCollection
     6         {
     7             new WebFormViewEngine(),
     8             new RazorViewEngine(),
     9         };
    10  
    11         public static ViewEngineCollection Engines
    12         {
    13             get { return _engines; }
    14         }
    15     }
    16 }

    这就是为什么ASP.NET MVC既支持*.aspx,又支持*.cshtml的原因了(个人觉得如果已经确定要使用RazorView的话,不如把WebFormViewEngine给移除,可能对性能会有所帮助)。

    那为什么所有的视图都要放在Views目录下呢,这个就要拜RazorViewngines所赐了。

    下面是RazorViewEngine的构造函数:

     1         public RazorViewEngine(IViewPageActivator viewPageActivator)
     2             : base(viewPageActivator)
     3         {
     4             AreaViewLocationFormats = new[]
     5             {
     6                 "~/Areas/{2}/Views/{1}/{0}.cshtml",
     7                 "~/Areas/{2}/Views/{1}/{0}.vbhtml",
     8                 "~/Areas/{2}/Views/Shared/{0}.cshtml",
     9                 "~/Areas/{2}/Views/Shared/{0}.vbhtml"
    10             };
    11             AreaMasterLocationFormats = new[]
    12             {
    13                 "~/Areas/{2}/Views/{1}/{0}.cshtml",
    14                 "~/Areas/{2}/Views/{1}/{0}.vbhtml",
    15                 "~/Areas/{2}/Views/Shared/{0}.cshtml",
    16                 "~/Areas/{2}/Views/Shared/{0}.vbhtml"
    17             };
    18             AreaPartialViewLocationFormats = new[]
    19             {
    20                 "~/Areas/{2}/Views/{1}/{0}.cshtml",
    21                 "~/Areas/{2}/Views/{1}/{0}.vbhtml",
    22                 "~/Areas/{2}/Views/Shared/{0}.cshtml",
    23                 "~/Areas/{2}/Views/Shared/{0}.vbhtml"
    24             };
    25  
    26             ViewLocationFormats = new[]
    27             {
    28                 "~/Views/{1}/{0}.cshtml",
    29                 "~/Views/{1}/{0}.vbhtml",
    30                 "~/Views/Shared/{0}.cshtml",
    31                 "~/Views/Shared/{0}.vbhtml"
    32             };
    33             MasterLocationFormats = new[]
    34             {
    35                 "~/Views/{1}/{0}.cshtml",
    36                 "~/Views/{1}/{0}.vbhtml",
    37                 "~/Views/Shared/{0}.cshtml",
    38                 "~/Views/Shared/{0}.vbhtml"
    39             };
    40             PartialViewLocationFormats = new[]
    41             {
    42                 "~/Views/{1}/{0}.cshtml",
    43                 "~/Views/{1}/{0}.vbhtml",
    44                 "~/Views/Shared/{0}.cshtml",
    45                 "~/Views/Shared/{0}.vbhtml"
    46             };
    47  
    48             FileExtensions = new[]
    49             {
    50                 "cshtml",
    51                 "vbhtml",
    52             };
    53         }

    所有的寻址路径都被格式化了,是不是很眼熟呢,关于这里为啥用数组而不用List,个人觉得,数组的寻址效率要更高些,遍历速度更快。

    好了,找了“罪魁祸首”,就好好地调教一个,让它乖乖听话,小样让去哪就去哪里。

     1  /// <summary>
     2     /// razor视图引擎扩展
     3     /// </summary>
     4     public class CustomerViewEngine : RazorViewEngine
     5     {
     6         /// <summary>
     7         /// 可以分开部署不同语种
     8         /// </summary>
     9         /// <param name="engineName"></param>
    10         public CustomerViewEngine(string engineName)
    11         {
    12             base.ViewLocationFormats = new[]
    13                 {
    14                     "~/Views" + engineName + "/{1}/{0}.cshtml",
    15                     "~/Views" + engineName + "/Shared/{0}.cshtml"
    16                 };
    17 
    18             base.PartialViewLocationFormats = new[]
    19                 {
    20                     "~/Views" + engineName + "/{1}/{0}.cshtml",
    21                     "~/Views" + engineName + "/Shared/{0}.cshtml"
    22                 };
    23 
    24             base.AreaViewLocationFormats = new[]
    25                 {
    26                     "~Areas/{2}/Views" + engineName + "/{1}/{0}.cshtml",
    27                     "~Areas/{2}/Views" + engineName + "/Shared/{0}.cshtml"
    28                 };
    29 
    30             base.AreaPartialViewLocationFormats = new[]
    31                 {
    32                     "~Areas/{2}/Views" + engineName + "/{1}/{0}.cshtml",
    33                     "~Areas/{2}/Views" + engineName + "/Shared/{0}.cshtml"
    34                 };
    35         }
    36 
    37         public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
    38         {
    39             this.SetEngine(controllerContext);
    40             return base.FindView(controllerContext, viewName, masterName, useCache);
    41         }
    42 
    43         public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
    44         {
    45             this.SetEngine(controllerContext);
    46             return base.FindPartialView(controllerContext, partialViewName, useCache);
    47         }
    48 
    49         /// <summary>
    50         /// 根据条件自行设置,目前是chrome浏览器就展示默认的
    51         /// 不是chrome浏览器的话就展示/Themes/Eleven下的
    52         /// 可以直接测试是移动端还是pc端
    53         /// 然后写入cookie
    54         /// </summary>
    55         private void SetEngine(ControllerContext controllerContext)
    56         {
    57             string engineName = "/Themes/Eleven";
    58             if (controllerContext.HttpContext.Request.UserAgent.IndexOf("Chrome/65") >= 0)
    59             {
    60                 engineName = null;
    61             }
    62 
    63             //if (controllerContext.HttpContext.Request.IsMobile())//检测是不是移动端
    64             //{
    65             //    engineName = null;
    66             //}
    67 
    68             base.ViewLocationFormats = new[]
    69                {
    70                     "~/Views" + engineName + "/{1}/{0}.cshtml",
    71                     "~/Views" + engineName + "/Shared/{0}.cshtml"
    72                 };
    73 
    74             base.PartialViewLocationFormats = new[]
    75                 {
    76                     "~/Views" + engineName + "/{1}/{0}.cshtml",
    77                     "~/Views" + engineName + "/Shared/{0}.cshtml"
    78                 };
    79 
    80             base.AreaViewLocationFormats = new[]
    81                 {
    82                     "~Areas/{2}/Views" + engineName + "/{1}/{0}.cshtml",
    83                     "~Areas/{2}/Views" + engineName + "/Shared/{0}.cshtml"
    84                 };
    85 
    86             base.AreaPartialViewLocationFormats = new[]
    87                 {
    88                     "~Areas/{2}/Views" + engineName + "/{1}/{0}.cshtml",
    89                     "~Areas/{2}/Views" + engineName + "/Shared/{0}.cshtml"
    90                 };
    91         }

    接下去就很简单了,只需要把原来的视图引擎清空,加载自己的视图引擎就可以了

     1         protected void Application_Start()
     2         {
     3             AreaRegistration.RegisterAllAreas();
     4  
     5             ViewEngines.Engines.Clear();
     6  
     7             ViewEngines.Engines.Add(new CustomViewEngine());
     8  
     9             RegisterGlobalFilters(GlobalFilters.Filters);
    10             RegisterRoutes(RouteTable.Routes);
    11         }
  • 相关阅读:
    java集合-方法
    Java线程池
    java疯狂讲义第18章类的加载和反射
    java疯狂讲义第16章多线程
    JAVA集合-HashMap的实现原理
    类加载-java new一个对象的过程发生了什么/Java对象创建过程
    JVM-java垃圾回收
    JVM-java内存区域
    JVM-java堆-新生代和老年代
    448. 找到所有数组中消失的数字
  • 原文地址:https://www.cnblogs.com/saodiseng2015/p/9742283.html
Copyright © 2020-2023  润新知