Fork me on GitHub
代码改变世界

修改MVC视图默认搜索规则(IViewEngine)

2016-08-24 11:55  沉睡的木木夕  阅读(1082)  评论(0编辑  收藏  举报

 前几天我自己在写一个系统,写到后台管理系统的时候,我突然有个想法就是:想在区域视图下新建文件,单独处理后台一些业务:Area/AdminManager/View/Content/Index.cshtml;这么一个路径,我刚建完就发现有点不对了,因为根据mvc默认的规则就是ControllerName/ViewName,所以我不管怎么新建文件夹,视图 都是在ManagerController控制下,换言之,到达浏览器的地址是这样的:Area/Manager/Index 而不是我们心中的:Area/AdminManager/Content/Index

好,有人想到了一种解决方案了:那就是修改路由;

的确,我也想到了这种方法。预示我就在区域视图下修改路由:

context.MapRoute(
  "Managercontent",
  "manager/{controller}/{action}/{id}",
  new{action = "default",id=UrlParameter.Optional}  
);

然后在controllers文件夹中新建一个专门处理后台某块业务的控制器——ContentController

然后运行,结果还是曝黄页,显示的内容是404,没有找到指定路径下的视图文件,我看了黄页的内容,是这样的

未找到“XXX”视图,...搜索了以下位置:
~/Area/AdminManage/Views/Content/Welcome.cshtml
~/Area/AdminManage/Views/Content/Welcome.vbhtml
~/Area/AdminManage/Views/Shared/Welcome.cshtml
~/Area/AdminManage/Views/Shared/Welcome.vbhtml
~/Views/Content/Welcome.cshtml
~/Views/Content/Welcome.vbhtml
~/Views/Shared/Welcome.cshtml
~/Views/Shared/Welcome.vbhtml

看到这个信息之后,我心中的想法就是:怎么mvc找的是这些指定的路径?怎么不去找我新建的~/Area/AdminManage/Views/Manage/Content/Welcome.cshtml

我研究了下规律,因为是区域,所以搜索视图前面的Area/AdminManage/Views/是固定的,后面的Content/Welcome.cshtml中的Content是控制器名称,welcome是action名称

那么也就是说mvc框架默认的查找视图的路径就是这样的,只在Views根目录下找,而不去找它的子目录,那么如何修改这个规则呢?mvc不是“约定优于配置”的嘛

肯定是跟试图引擎IViewEngine有关,我带着疑问去网上找资料,果然解决方案还是很多的,下面我参照网上的做法:

/// <summary>
    /// 修改视图引擎搜索视图文件规则
    /// </summary>
    public sealed class MultipleEngineHelper : RazorViewEngine
    {
        public MultipleEngineHelper() {
            ViewLocationFormats = new[]
            {
                "~/Views/{1}/{0}.cshtml",
                "~/Views/Shared/{0}.cshtml",
                "~/Areas/AdminManage/Views/Manage/{1}/{0}.cshtml",
            };
        }

        public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
        {
            return base.FindView(controllerContext, viewName, masterName, useCache);
        }
    }

光有这个还没用,还需要在Gloab添加注册

proteced void Application_Start(){
     ....
     RegisterView();
}

private void RegisterView()
{
      ViewEngines.Engines.Clear();
      ViewEngines.Engines.Add(new MultipleEngineHelper());
}

这样我们重新正常运行啦!