Mvc系统学习9——Areas学习
在Mvc2.0中,新增加了一个特性就是Areas。在没有有使用Areas的情况下,我们的Mvc项目组织是下面这样的。当项目庞大的时候,Controllers,Model,View文件下下面势必会有很多文件。项目将难以管理。
通过使用Areas使我们可以很好的组织项目,通过单机添加Areas(区域),使用Areas来组织项目。可以得到新的项目组织结构。
First,Second对应着我们项目的子模块(First,Second命名不是很好)。在这两个文件夹下,有各自独立的Controllers,Models,Views。此外还多了个文件AreaRegistration为后缀的.cs文件. 这个文件主要的作用是给Areas下的子模块配置路由。在全局文件Global.asax中的Application_Start事件里有这么一句代码 AreaRegistration.RegisterAllAreas(),通过mvc源码可以发现通过这句代码最后会调用各个AreaRegistration类,实现路由的注册。
//重写了AreaName用于给DataToken["area"]赋值 public class FirstAreaRegistration : AreaRegistration { public override string AreaName { get { return "First"; } } //这里会添加一个相应的Area名称的前缀,因为下面这样的添加也是作用到全局路由表的. //而且这里的MapRoutes,和在全局的MapRoutes是不同的 //这时AreaRegistrationContext里面的方法,它里面的方法会自动给DataToken["area"]键赋值当前的AreaName public override void RegisterArea(AreaRegistrationContext context) { context.MapRoute( "First_default", "First/{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); }
当调用 AreaRegistration.RegisterAllAreas()时,会最后调用下面这个方法。通过下面的代码可以得出,这个方法会通过反射得出所有的AreaRegistration的Type实例。接下来依次通过Activator创建实例,进而调用CreateContentAndRegister方法。\
internal static void RegisterAllAreas(RouteCollection routes, IBuildManager buildManager, object state) { List<Type> areaRegistrationTypes = TypeCacheUtil.GetFilteredTypesFromAssemblies(_typeCacheName, IsAreaRegistrationType, buildManager); foreach (Type areaRegistrationType in areaRegistrationTypes) { AreaRegistration registration = (AreaRegistration)Activator.CreateInstance(areaRegistrationType); registration.CreateContextAndRegister(routes, state); } }
registration.CreateContextAndRegister方法:
internal void CreateContextAndRegister(RouteCollection routes, object state) { //实例化一个AreaRegistrationContext 实例,AreaName已经传递给AreaRegistrationContext了 AreaRegistrationContext context = new AreaRegistrationContext(AreaName, routes, state); string thisNamespace = GetType().Namespace; if (thisNamespace != null) { context.Namespaces.Add(thisNamespace + ".*"); } //调用注册方法,这个方法在各个AreaRegistration中被重写 RegisterArea(context); }
各个AreaRegistration重写的RegisterArea(context)方法里面通过调用AreaRegistrationContext的Maproute方法来实现注册,这个方法最后的调用方法是下面这个。可以发现下面这个方法也会调用RouteCollection的MapRoute方法,调用这个方法之后,又向route的DataTokens字典的area和UseNamespaceFallback键设置值。这有什么作用?
public Route MapRoute(string name, string url, object defaults, object constraints, string[] namespaces) { if (namespaces == null && Namespaces != null) { namespaces = Namespaces.ToArray(); } Route route = Routes.MapRoute(name, url, defaults, constraints, namespaces); route.DataTokens["area"] = AreaName; // disabling the namespace lookup fallback mechanism keeps this areas from accidentally picking up // controllers belonging to other areas bool useNamespaceFallback = (namespaces == null || namespaces.Length == 0); route.DataTokens["UseNamespaceFallback"] = useNamespaceFallback; return route; }
还有几个疑问待解决:
1.Area下的路由过程是怎么样的?
2.在Area下可以实现不同的Area有相同的ControllerName,可以在全局的Global.ascx进行文件配置,但是如果是同名的Controller则会出现错误,而对没有同名的Controller进行配置则不会,这是为什么?
比如在First,Second都有HomeController,如果在全局的Global.ascx文件进行配置,下面的配置不会出错,但是如果namespaces是MvcAreaDemo2.Areas.First时则会出现错误。这时为什么?如果没有用同名的Controller则namespace是MvcAreaDemo2.Areas.First和MvcAreaDemo2.Areas.First.Controllers都没有错。
routes.Add(new Route("Index1", new MvcRouteHandler()) { Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = UrlParameter.Optional }), DataTokens = new RouteValueDictionary(new { area = "First", namespaces = new[] { "MvcAreaDemo2.Areas.First.Controllers" } }) }); routes.Add(new Route("Index2", new MvcRouteHandler()) { Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = UrlParameter.Optional }), DataTokens = new RouteValueDictionary(new { area = "Second", namespaces = new[] { "MvcAreaDemo2.Areas.Second.Controllers" } }) });
3.在Area的使用况下,如果要跳转到另外一个Area的页面,则使用Html.ActionLink进行编写似乎更加麻烦了,有木有更加简便的方法?
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。