自定义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

你可能感兴趣的:(Engine)