思路:
1 需要添加 AreaRouteHeler,便于创建控制器分组信息。
2 添加自定义视图引擎,为了控制器能够导航到各Area中的页面。
步骤:
1 . 添加 AreaRouteHeler。
- /// <summary>
- /// 控件器分组帮助类
- /// </summary>
- public class AreaRouteHeler
- {
- /// <summary>
- /// 创建控制器域
- /// </summary>
- /// <param name="routeCollection">路由集合</param>
- /// <param name="areaName">控制器域</param>
- /// <param name="controllerNameSpace">控制器NameSpace</param>
- /// <param name="routeEntries">路由参数(可多个)</param>
- public static void CreateArea(this RouteCollection routeCollection, string areaName, string controllerNameSpace, params Route[] routeEntries)
- {
- if (routeEntries == null || routeEntries.Length <= 0)
- {
- return;
- }
- foreach (Route route in routeEntries)
- {
- if (route.Constraints == null)
- {
- route.Constraints = new RouteValueDictionary();
- }
- if (route.Defaults == null)
- {
- route.Defaults = new RouteValueDictionary();
- }
- if (route.DataTokens == null)
- {
- route.DataTokens = new RouteValueDictionary();
- }
- route.Constraints.Add("area", areaName);
- route.DataTokens.Add("namespaces", new[] { controllerNameSpace });
- route.Defaults.Add("area", areaName);
- //To support "new Route()" in addition to "routes.MapRoute()"
- if (!routeCollection.Contains(route))
- {
- routeCollection.Add(route);
- }
- }
- }
- }
- 2. 添加自定义视图引擎.
- /// <summary>
- /// 控件器分组视图引擎
- /// </summary>
- public class AreaViewEngine : WebFormViewEngine
- {
- public AreaViewEngine()
- : base()
- {
- // 视图位置匹配规则设置
- ViewLocationFormats = new string[]
- {
- "~/{0}.aspx",
- "~/{0}.ascx",
- "~/Views/{1}/{0}.aspx",
- "~/Views/{1}/{0}.ascx",
- "~/Views/Shared/{0}.aspx",
- "~/Views/Shared/{0}.ascx",
- };
- // 母版页匹配规则设置
- MasterLocationFormats = new string[]
- {
- "~/{0}.master",
- "~/Shared/{0}.master",
- "~/Views/{1}/{0}.master",
- "~/Views/Shared/{0}.master",
- };
- }
- #region override父类
- /// <summary>
- /// 寻找局部视图
- /// </summary>
- /// <param name="controllerContext">ControllerBase和HttpContextBase的上下文</param>
- /// <param name="partialViewName">局部视图名称</param>
- /// <param name="useCache">是否缓存</param>
- /// <returns>结果</returns>
- public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
- {
- ViewEngineResult areaResult = null;
- // 判断是否存在当前的控制器分组
- if (controllerContext.RouteData.Values.ContainsKey("area"))
- {
- // 寻找局部视图
- string areaPartialName = FormatViewName(controllerContext, partialViewName);
- areaResult = base.FindPartialView(controllerContext, areaPartialName, useCache);
- if (areaResult != null && areaResult.View != null)
- {
- return areaResult;
- }
- // 寻找共享部分的视图
- string sharedAreaPartialName = FormatSharedViewName(controllerContext, partialViewName);
- areaResult = base.FindPartialView(controllerContext, sharedAreaPartialName, useCache);
- if (areaResult != null && areaResult.View != null)
- {
- return areaResult;
- }
- }
- // 如果均没找着,按MVC默认寻找视图。
- return base.FindPartialView(controllerContext, partialViewName, useCache);
- }
- /// <summary>
- /// 寻找视图
- /// </summary>
- /// <param name="controllerContext">控制器上下文对象</param>
- /// <param name="viewName">视图名称</param>
- /// <param name="masterName">母版页</param>
- /// <param name="useCache">是否缓存</param>
- /// <returns>结果</returns>
- public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
- {
- ViewEngineResult areaResult = null;
- if (controllerContext.RouteData.Values.ContainsKey("area"))
- {
- string areaViewName = FormatViewName(controllerContext, viewName);
- areaResult = base.FindView(controllerContext, areaViewName, masterName, useCache);
- if (areaResult != null && areaResult.View != null)
- {
- return areaResult;
- }
- string sharedAreaViewName = FormatSharedViewName(controllerContext, viewName);
- areaResult = base.FindView(controllerContext, sharedAreaViewName, masterName, useCache);
- if (areaResult != null && areaResult.View != null)
- {
- return areaResult;
- }
- }
- return base.FindView(controllerContext, viewName, masterName, useCache);
- }
- #endregion
- private static string FormatViewName(ControllerContext controllerContext, string viewName)
- {
- string controllerName = controllerContext.RouteData.GetRequiredString("controller");
- string area = controllerContext.RouteData.Values["area"].ToString();
- return string.Format("Areas/{0}/Views/{1}/{2}" , area, controllerName ,viewName);
- }
- private static string FormatSharedViewName(ControllerContext controllerContext, string viewName)
- {
- string area = controllerContext.RouteData.Values["area"].ToString();
- return string.Format("Areas/{0}/Views/Shared/{1}", area, viewName);
- }
- }
如何使用呢?
这个就是轻车熟路了,去全局应用程序类中进行配置控件器分组、注册视图引擎,就可以了。
a. 设置不同的控制器项
- public static void RegisterRoutes(RouteCollection routes)
- {
- routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
- // Account控制器组
- routes.CreateArea("Account", "WT.TTC.UI.Areas.Account.Controllers",
- routes.MapRoute(null, "Account/{controller}/{action}", new { controller = "Account", action = "Index" }));
- // UserCenter控制器组
- routes.CreateArea("UserCenter", "WT.TTC.UI.Areas.UserCenter.Controllers",
- routes.MapRoute("IndexPage2", "UserCenter/{controller}/{action}", new { controller = "Home", action = "Index" }));
- // root,根目录
- routes.CreateArea("Root", "WT.TTC.UI.Controllers.HomeController",
- routes.MapRoute("IndexPage3-必须唯一", "UserCenter/{controller}/{action}", new { controller = "Home", action = "Index" }));
- }
b. 设置视图引擎
- protected void Application_Start()
- {
- // 添加视图引擎
- ViewEngines.Engines.Clear();
- ViewEngines.Engines.Add(new AreaViewEngine());
- RegisterRoutes(RouteTable.Routes);
- }
输入url:
http://localhost:5459/account/account/index
http://localhost:5459/UserCenter/Home/index
结果:能够正常导航。一切OK结束。
注意一件事:
routes.MapRoute(null, "Account/{controller}/{action}".......
routes.MapRoute(“IndexPage2”, "Account/{controller}/{action}".......
routes.MapRoute("IndexPage3-必须唯一", "UserCenter/{controller}/{action}".......
我们发现:routes.MapRoute方法第一个参数,路由名称不能重复;或者为null值,但不推荐这么做,假如哪一天你可trace,有一个名字是不是好很多?
在此间中出现了一个大黄页错误:
未能加载类型“System.Web.Mvc.ViewPage<dynamic>”。
在Web.config文件的pages节点加入即可,原因应该是缺少配置,导致反射生成类型失败。
- <pages validateRequest="false" pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
- pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
- userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">