分类:
版权声明:本文为博主原创文章,未经博主允许不得转载。
ASP.NET MVC出来这么久了,心中却又很多的疑惑:为什么所有的View都要放在Views目录下? 为什么Shared文件夹下面的页面可以被共享? 为什么Page既可以是*.cshtml,也可以是*.aspx?
其实上面的几个问题归结起来都是视图引擎的功效。
在传统的ASP.NET中,可能还没有ViewEngine的概念。因为在Web From里面,实现Page实现了IHttpHanlder的接口,所以Page既是响应的处理类,也是视图的渲染类。在ASP.NET MVC中,视图的概念被抽象了出来,试图引擎的概念也被抽象成了一个接口。
首先来看一下IViewEngine接口的定义:
- namespace System.Web.Mvc
- {
- public interface IViewEngine
- {
- ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache);
- ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache);
- void ReleaseView(ControllerContext controllerContext, IView view);
- }
- }
总共3个函数,总结起来大概就是两个功能:Find & Release。
默认情况下,ASP.NET MVC提供了两个视图引擎:WebFormViewEngine和RazorViewEngine。
- namespace System.Web.Mvc
- {
- public static class ViewEngines
- {
- private static readonly ViewEngineCollection _engines = new ViewEngineCollection
- {
- new WebFormViewEngine(),
- new RazorViewEngine(),
- };
- public static ViewEngineCollection Engines
- {
- get { return _engines; }
- }
- }
- }
这就是为什么ASP.NET MVC既支持*.aspx,又支持*.cshtml的原因了(个人觉得如果已经确定要使用RazorView的话,不如把WebFormViewEngine给移除,可能对性能会有所帮助)。
那为什么所有的视图都要放在Views目录下呢,这个就要拜RazorViewngines所赐了。
下面是RazorViewEngine的构造函数:
- public RazorViewEngine(IViewPageActivator viewPageActivator)
- : base(viewPageActivator)
- {
- AreaViewLocationFormats = new[]
- {
- "~/Areas/{2}/Views/{1}/{0}.cshtml",
- "~/Areas/{2}/Views/{1}/{0}.vbhtml",
- "~/Areas/{2}/Views/Shared/{0}.cshtml",
- "~/Areas/{2}/Views/Shared/{0}.vbhtml"
- };
- AreaMasterLocationFormats = new[]
- {
- "~/Areas/{2}/Views/{1}/{0}.cshtml",
- "~/Areas/{2}/Views/{1}/{0}.vbhtml",
- "~/Areas/{2}/Views/Shared/{0}.cshtml",
- "~/Areas/{2}/Views/Shared/{0}.vbhtml"
- };
- AreaPartialViewLocationFormats = new[]
- {
- "~/Areas/{2}/Views/{1}/{0}.cshtml",
- "~/Areas/{2}/Views/{1}/{0}.vbhtml",
- "~/Areas/{2}/Views/Shared/{0}.cshtml",
- "~/Areas/{2}/Views/Shared/{0}.vbhtml"
- };
- ViewLocationFormats = new[]
- {
- "~/Views/{1}/{0}.cshtml",
- "~/Views/{1}/{0}.vbhtml",
- "~/Views/Shared/{0}.cshtml",
- "~/Views/Shared/{0}.vbhtml"
- };
- MasterLocationFormats = new[]
- {
- "~/Views/{1}/{0}.cshtml",
- "~/Views/{1}/{0}.vbhtml",
- "~/Views/Shared/{0}.cshtml",
- "~/Views/Shared/{0}.vbhtml"
- };
- PartialViewLocationFormats = new[]
- {
- "~/Views/{1}/{0}.cshtml",
- "~/Views/{1}/{0}.vbhtml",
- "~/Views/Shared/{0}.cshtml",
- "~/Views/Shared/{0}.vbhtml"
- };
- FileExtensions = new[]
- {
- "cshtml",
- "vbhtml",
- };
- }
所有的寻址路径都被格式化了,是不是很眼熟呢,关于这里为啥用数组而不用List,个人觉得,数组的寻址效率要更高些,遍历速度更快。
好了,找了“罪魁祸首”,就好好地调教一个,让它乖乖听话,小样让去哪就去哪里。
- namespace MvcApplicatin.Web.Mvc.ViewEngine
- {
- public sealed class CustomViewEngine : RazorViewEngine
- {
- public CustomViewEngine()
- {
- ViewLocationFormats = new[]
- {
- "~/Views/{1}/{0}.cshtml",
- "~/Views/Shared/{0}.cshtml",
- "~/CustomViewLocation/{1}/{0}.cshtml"
- };
- }
- public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
- {
- return base.FindView(controllerContext, viewName, masterName, useCache);
- }
- }
- }
我使用开发语言是C#,视图是Razor,所以稍稍修改了下ViewLocationFormats,让寻址路径能够寻到CustomViewLocation下面的视图。
接下去就很简单了,只需要把原来的视图引擎清空,加载自己的视图引擎就可以了。
- protected void Application_Start()
- {
- AreaRegistration.RegisterAllAreas();
- ViewEngines.Engines.Clear();
- ViewEngines.Engines.Add(new CustomViewEngine());
- RegisterGlobalFilters(GlobalFilters.Filters);
- RegisterRoutes(RouteTable.Routes);
- }