解读ASP.NET 5 & MVC6系列教程(16):自定义View视图文件查找逻辑
之前mvc5和之前的版本中,我们要想对view文件的路径进行控制的话,则必须要对iviewengine
接口的findpartialview
或findview
方法进行重写,所有的视图引擎都继承于该iviewengine
接口,比如默认的razorviewengine
。但新版本mvc6中,对视图文件的路径方式却不太一样了,目前有两种方式,一种是通过razorviewengine
,另外一种是通过新特性iviewlocationexpander
接口。
通过razorviewengine来控制view路径
在新版的razorviewengine
中,该类提供了两个虚属性(areaviewlocationformats
和viewlocationformats
),可以用于重写控制,而不必再对findpartialview
或findview
方法进行重写,示例如下:
public class themeviewengine : razorviewengine { public themeviewengine(irazorpagefactory pagefactory, irazorviewfactory viewfactory, iviewlocationexpanderprovider viewlocationexpanderprovider, iviewlocationcache viewlocationcache) : base(pagefactory, viewfactory, viewlocationexpanderprovider, viewlocationcache) { } public override ienumerable<string> areaviewlocationformats { get { var value = new random().next(0, 1); var theme = value == 0 ? "theme1" : "theme2"; // 可通过其它条件,设置皮肤的种类 return base.areaviewlocationformats.select(f => f.replace("/views/", "/views/" + theme + "/")); } } public override ienumerable<string> viewlocationformats { get { var value = new random().next(0, 1); var theme = value == 0 ? "theme1" : "theme2"; // 可通过其它条件,设置皮肤的种类 return base.viewlocationformats.select(f => f.replace("/views/", "/views/" + theme + "/")); } } }
然后,通过修改mvcoptions的实例属性viewengines即可完成对视图引擎的替换,代码如下:
services.addmvc().configure<mvcoptions>(options => { options.viewengines.clear(); options.viewengines.add(typeof(themeviewengine)); });
这样,系统在查找视图文件的时候,就会按照新注册的themeviewengine
的逻辑来执行。
通过iviewlocationexpander来控制view路径
在mvc6中,微软还提供了另外一种新的方式来控制view文件的路径,那就是iviewlocationexpander
接口,通过实现该接口即可实现自定义逻辑,并且也可以使用相关的上下文对象。示例如下:
public class themeviewlocationexpander : iviewlocationexpander { public void populatevalues(viewlocationexpandercontext context) { var value = new random().next(0, 1); var theme = value == 0 ? "theme1" : "theme2"; context.values["theme"] = theme; } public virtual ienumerable<string> expandviewlocations(viewlocationexpandercontext context, ienumerable<string> viewlocations) { return viewlocations.select(f => f.replace("/views/", "/views/" + context.values["theme"] + "/")); } }
在上述自定义的iviewlocationexpander
中,实现了2个方法分别是populatevalues
和expandviewlocations
,populatevalues
方法可以让我们想viewlocationexpandercontext
上下文中添加响应的键值对以便后续使用,通过,我们可以利用通过该上下文对象,来查找actioncontext
和httpcontext
对象,以便利用这些对象做响应的判断操作;而expandviewlocations
方法,只会在没有view缓存或在view缓存里找不到对应key的view文件时才会调用该方法,在该方法内,我们可以动态返回视图的位置。
最后,我们在startup.cs
里通过修改razorviewengineoptions
实例对象的viewlocationexpanders
属性,来实现注册目的,代码如下:
services.configure<razorviewengineoptions>(options => { options.viewlocationexpanders.add(typeof(themviewlocationexpander)); });