自定义ViewEngine

为什么需要自定义ViewEngine

我们先看一段最普通代码:

View Code
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }

上面的View查找路径为:

"~/Views/Home/Index.cshtml"

这是默认的ViewEngine(RazorViewEngine)的查找规则。当它不能满足我们特殊的View路径查找需求时,就需要通过自定义ViewEngine实现。

在nopCommerce中, 它的后台管理是一个单独的工程,工程路径为Web\Administration,访问admin/home/index时需要返回

"~/Administration/Views/Home/Index.cshtml"

实现方法

1,实现IViewEngine接口,但一般不这么做,原因是太费劲了

2,继承BuildManagerViewEngine,修改它的ViewLocationFormats参数。   

View Code
 public MyViewEngine(IViewPageActivator viewPageActivator)
        : base(viewPageActivator)
    {
        ViewLocationFormats = new[]{
            //default
            "~/Views/{1}/{0}.cshtml", 
            "~/Views/{1}/{0}.vbhtml", 
            "~/Views/Shared/{0}.cshtml",
            "~/Views/Shared/{0}.vbhtml",

            //Admin
            "~/administrator/Views/{1}/{0}.cshtml",
            "~/administrator/Views/{1}/{0}.vbhtml",
            "~/administrator/Views/Shared/{0}.cshtml",
            "~/administrator/Views/Shared/{0}.vbhtml",
        };

        FileExtensions = new[] {
            "cshtml"
        };
    }

    类关系:BuildManagerViewEngine:VirtualPathProviderViewEngine:IViewEngine

    最后只需在Global.asax中使用它:

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new MyViewEngine());

关于nopCommerce中的ViewEngine

按照上面思路实现的ViewEngine有一个缺陷,当项目中存在多个area,area下又存在相同的Controller和action时,返回的View将不正确。

nopCommerce的admin有一个HomeController,如主站点也有一个,上面的做法返回的View将一直是"~/Views/Home/Index.cshtml",因为它最先匹配。

解决办法:根据area通过动态修改areaLocations。

下面是部分关键代码(位于ThemeableVirtualPathProviderViewEngine.cs)

View Code
protected virtual string GetPath(ControllerContext controllerContext, string[] locations, string[] areaLocations, string locationsPropertyName, string name, string controllerName, string theme, string cacheKeyPrefix, bool useCache, bool mobile, out string[] searchedLocations)
        {
           .....
                var newLocations = areaLocations.ToList();
                newLocations.Insert(0, "~/Administration/Views/{1}/{0}.cshtml");
                newLocations.Insert(0, "~/Administration/Views/{1}/{0}.vbhtml");
                newLocations.Insert(0, "~/Administration/Views/Shared/{0}.cshtml");
                newLocations.Insert(0, "~/Administration/Views/Shared/{0}.vbhtml");
                areaLocations = newLocations.ToArray();
            }

         ......
        }

 

相关链接:Walkthrough: Creating an ASP.NET MVC Areas Application Using Multiple Projects

posted @ 2012-10-29 17:54  Season2009  阅读(385)  评论(0编辑  收藏  举报