人本善良

导航

asp.net mvc 多级文件夹

 

ASP.NET MVC - 定制属于你自己的ViewEngine

标签: asp.netmvcstring引擎razorapplication
 分类:

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

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

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

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

 

[csharp] view plain copy
 
  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。

 

[csharp] view plain copy
 
  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的构造函数:

 

[csharp] view plain copy
 
  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,个人觉得,数组的寻址效率要更高些,遍历速度更快。

 

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

 

[csharp] view plain copy
 
  1. namespace MvcApplicatin.Web.Mvc.ViewEngine  
  2. {  
  3.     public sealed class CustomViewEngine : RazorViewEngine  
  4.     {  
  5.   
  6.         public CustomViewEngine()  
  7.         {  
  8.             ViewLocationFormats = new[]  
  9.             {  
  10.                 "~/Views/{1}/{0}.cshtml",  
  11.                 "~/Views/Shared/{0}.cshtml",  
  12.                 "~/CustomViewLocation/{1}/{0}.cshtml"  
  13.             };  
  14.         }  
  15.         public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)  
  16.         {  
  17.             return base.FindView(controllerContext, viewName, masterName, useCache);  
  18.         }  
  19.     }  
  20. }  

我使用开发语言是C#,视图是Razor,所以稍稍修改了下ViewLocationFormats,让寻址路径能够寻到CustomViewLocation下面的视图。

 

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

 

[csharp] view plain copy
 
  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. }  

 

posted on 2016-09-24 18:02  简简单单2018  阅读(480)  评论(0编辑  收藏  举报