ASP.NET MVC扩展自定义视图引擎支持多模板&动态换肤skins机制
ASP.NET mvc的razor视图引擎是一个非常好的.NET MVC框架内置的视图引擎。一般情况我们使用.NET MVC框架为我们提供的这个Razor视图引擎就足够了。但是有时我们想在我们的项目支持多模板&skins机制,比如我们可能会有多套的模板,也就是多个View风格,而我们只需要改一下配置文件就可以轻松的改变页面的风格和模板。实现这个功能有两种方式:
一、使用接口IViewEngine自己完成一个类似Razor视图引擎的功能。
二、继承类RazorViewEngine类,重写它的一些方法达到自定义视图引擎的目的。
显然方法二是最简单的,因此我们选最简单方式实现这个功能。
1、首先,我们定义一个一些基础的辅助类
标示支持Skin特性类:
1 using System; 2 /// <summary> 3 /// 用于标示支持Skin换肤的特性 4 /// </summary> 5 public class SupportSkinAttribute : Attribute 6 { 7 8 }
风格配置结点读取类:
1 using System; 2 using System.Configuration; 3 using System.Web; 4 5 public class Utils 6 { 7 private static string _skinName; 8 9 public static string SkinName 10 { 11 get 12 { 13 if (!string.IsNullOrEmpty(_skinName)) 14 { 15 return _skinName; 16 } 17 //模板风格 18 _skinName = ConfigurationManager.AppSettings["Skin"]; 19 return _skinName; 20 } 21 } 22 }
Helper类:
1 public class CustomViewEngineHelper 2 { 3 internal static string[] AddNewLocationFormats(IEnumerable<string> defaultLocationFormats,IEnumerable<string> newLocationFormats) 4 { 5 List<string> allItems = new List<string>(newLocationFormats); 6 foreach (string s in defaultLocationFormats) 7 { 8 allItems.Add(s); 9 } 10 11 return allItems.ToArray(); 12 } 13 14 15 internal static string OverrideMasterPage(string masterName, ControllerContext controllerContext) 16 { 17 if (NeedChangeMasterPage(controllerContext)) 18 { 19 masterName = Utils.SkinName; 20 } 21 22 return masterName; 23 } 24 25 private static bool NeedChangeMasterPage(ControllerContext context) 26 { 27 SupportSkinAttribute attr = Attribute.GetCustomAttribute(context.Controller.GetType(), typeof (SupportSkinAttribute)) as SupportSkinAttribute; 28 return null != attr; 29 } 30 }
2、然后,定义CustomRazorViewEngine类
CustomRazorViewEngine.cs:
1 public class CustomRazorViewEngine : RazorViewEngine 2 { 3 public CustomRazorViewEngine() 4 { 5 string[] mastersLocation = new[]{string.Format("~/skins/{0}/views/{0}.cshtml", Utils.SkinName)}; 6 MasterLocationFormats = CustomViewEngineHelper.AddNewLocationFormats( 7 new List<string>(MasterLocationFormats), 8 mastersLocation); 9 10 string[] viewsLocation = new[]{ string.Format("~/skins/{0}/Views/{{1}}/{{0}}.cshtml",Utils.SkinName)}; 11 //视图文件位置路径的格式 12 ViewLocationFormats = 13 PartialViewLocationFormats = 14 CustomViewEngineHelper.AddNewLocationFormats(new List<string>(ViewLocationFormats), viewsLocation); 15 } 16 17 //查找视图文件 18 public override ViewEngineResult FindView(ControllerContext controllerContext,string viewName,string masterName,bool useCache) 19 { 20 masterName = CustomViewEngineHelper.OverrideMasterPage(masterName,controllerContext); 21 return base.FindView(controllerContext,viewName, masterName,useCache); 22 } 23 }
上面代码是最核心的部分,我们在CustomRazorViewEngine类构造函数中就按照我们自定约定规则重写了MasterLocationFormats(~/skins/{0}/views/{0}.cshtml)和ViewLocationFormats(~/skins/{0}/Views/{{1}}/{{0}}.cshtml)属性,最后在FindView方法中重写了master的文件名。
如果风格名为lanhu,将按照以下的规则来创建视图文件:
1、MasterLocationFormats(Layout)路径为:~/skins/lanhu/views/lanhu.cshtml
2、ViewLocationFormats(视图文件)路径为:~/skins/lanhu/Views/{1}/{0}.cshtml,其中{1}和{0}分别表示Controller和Action的名字。
3、最后,注册CustomRazorViewEngine
最后,在Appication_Start中加入下面的代码,使用CustomRazorViewEngine生效
1 ViewEngines.Engines.Clear(); 2 ViewEngines.Engines.Add(new CustomRazorViewEngine());
上面第一行是清除默认的视图引擎,接下来把我们自定义的CustomRazorViewEngine注册到MVC框架中使用其生效。
使用CustomRazorViewEngine提供的多模板&skins换肤机制,要在Controller类前面加上特性SupportSkin,如下代码:
1 [SupportSkin] 2 public class HomeController 3 { 4 //省略其它代码 5 }
这样ASP.NET MVC视图引擎就支持多模板&skins换肤机制了,我们只需要增加一个风格,在skins文件夹中创建自己的风格的文件夹,并添加相应的视图。最后,在把Web.config的配置结点名为Skin的值改成,相应的风格名称(即skins文件夹的文件夹名),我们以后想换模板就是分分钟的事。