MVC ViewEngine视图引擎解读及autofac的IOC运用实践
MVC 三大特色 Model、View、Control ,这次咱们讲视图引擎ViewEngine
1.首先看看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); } }
2.默认情况下,ASP.NET MVC提供2种视图引擎: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的原因了。
那为什么所有的视图都要放在Views目录下呢,这个就要拜RazorViewngines所赐了。
namespace System.Web.Mvc { public class RazorViewEngine : BuildManagerViewEngine { internal static readonly string ViewStartFileName = "_ViewStart"; public RazorViewEngine() : this(null) { } 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", }; } protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) { return new RazorView(controllerContext, partialPath, layoutPath: null, runViewStartPages: false, viewStartFileExtensions: FileExtensions,
viewPageActivator: ViewPageActivator) { DisplayModeProvider = DisplayModeProvider }; } protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) { var view = new RazorView(controllerContext, viewPath, layoutPath: masterPath, runViewStartPages: true, viewStartFileExtensions: FileExtensions, viewPageActivator: V iewPageActivator) { DisplayModeProvider = DisplayModeProvider }; return view; } } }
知道RazorViewEngine 内部定义,现在可以定制自己的需求啦
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); } }
接下去就很简单了,只需要把原来的视图引擎清空,加载自己的视图引擎就可以了。
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(new CustomViewEngine()); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); }
这样可以改变展示页面必须在View下的显示的局面,从而更加的灵活,为视图从Views拿出去 提供了必要条件,还需要一些其他操作:
这个时候很明显,已经开始在我们自定义加的视图文件夹下面开始找视图了.但是找到了,却提示这个视图文件没派生自 WebViewPage 或 WebViewPage<TModel>。
我们知道Razor视图最终都会编译成一个类,这个类会自动继承WebViewPage 或 WebViewPage<TModel>,(这个是强类型视图了..)(大家可以用反编译工具看见)
但是我们把视图从Views下面拿出来了, MVC框架就不会编译的时候让他继承WebViewPage 或 WebViewPage<TModel>
解决方案:
第一种:这种最简单.把Views下面的web.config文件复制一个到MyCustomView下面,这样错误就没有了!就可以正常访问找到视图了
原理就是
上图中Views文件夹下面的Web.config中有一个节点配置了这么一句话<pages pageBaseType="System.Web.Mvc.WebViewPage"> .很明显是继承WebViewPage 的意思
有这个,此文件夹里面所有的视图编译的时候会自动运行这个,肯定就继承了WebViewPage
视图文件多的时候很适合这样做哦
我们知道ASP.NET框架对Web.config是 有就近原则和继承原则的,也就是你在网站根目录的Web.config下面的配置,适用于网站下面所有的程序,当你在子文件下面再有Web.config 的时候,他会就近选择使用(如果配置局部,想不使用全局配置,就可以自己加一个配置文件哦,是不是有点类似CSS中的就近原则,哈哈)
第二种:直接在视图中加一句指令
@inherits System.Web.Mvc.WebViewPage
作用不言而喻,当前视图会继承WebViewPage ,但多个视图的时候每个里面都写一句这个烦不烦!!所以不推挤这个啦!
参考链接:http://www.cnblogs.com/chengxiaohui/articles/4837193.html
http://blog.csdn.net/jackvs/article/details/7788743