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类,实现路由的注册。

View Code
1 //重写了AreaName用于给DataToken["area"]赋值
2   public class FirstAreaRegistration : AreaRegistration
3 {
4 public override string AreaName
5 {
6 get
7 {
8 return "First";
9 }
10 }
11
12 //这里会添加一个相应的Area名称的前缀,因为下面这样的添加也是作用到全局路由表的.
13 //而且这里的MapRoutes,和在全局的MapRoutes是不同的
14 //这时AreaRegistrationContext里面的方法,它里面的方法会自动给DataToken["area"]键赋值当前的AreaName
15   public override void RegisterArea(AreaRegistrationContext context)
16 {
17 context.MapRoute(
18 "First_default",
19 "First/{controller}/{action}/{id}",
20 new { controller = "Home", action = "Index", id = UrlParameter.Optional }
21 );
22 }

       当调用 AreaRegistration.RegisterAllAreas()时,会最后调用下面这个方法。通过下面的代码可以得出,这个方法会通过反射得出所有的AreaRegistration的Type实例。接下来依次通过Activator创建实例,进而调用CreateContentAndRegister方法。

View Code
1 internal static void RegisterAllAreas(RouteCollection routes, IBuildManager buildManager, object state) {
2 List<Type> areaRegistrationTypes = TypeCacheUtil.GetFilteredTypesFromAssemblies(_typeCacheName, IsAreaRegistrationType, buildManager);
3 foreach (Type areaRegistrationType in areaRegistrationTypes) {
4 AreaRegistration registration = (AreaRegistration)Activator.CreateInstance(areaRegistrationType);
5 registration.CreateContextAndRegister(routes, state);
6 }
7 }

       registration.CreateContextAndRegister方法:

View Code
1 internal void CreateContextAndRegister(RouteCollection routes, object state) {
2 //实例化一个AreaRegistrationContext 实例,AreaName已经传递给AreaRegistrationContext了
3   AreaRegistrationContext context = new AreaRegistrationContext(AreaName, routes, state);
4
5 string thisNamespace = GetType().Namespace;
6 if (thisNamespace != null) {
7 context.Namespaces.Add(thisNamespace + ".*");
8 }
9 //调用注册方法,这个方法在各个AreaRegistration中被重写
10   RegisterArea(context);
11 }

      各个AreaRegistration重写的RegisterArea(context)方法里面通过调用AreaRegistrationContext的Maproute方法来实现注册,这个方法最后的调用方法是下面这个。可以发现下面这个方法也会调用RouteCollection的MapRoute方法,调用这个方法之后,又向route的DataTokens字典的area和UseNamespaceFallback键设置值。这有什么作用?

View Code
1 public Route MapRoute(string name, string url, object defaults, object constraints, string[] namespaces) {
2 if (namespaces == null && Namespaces != null) {
3 namespaces = Namespaces.ToArray();
4 }
5
6 Route route = Routes.MapRoute(name, url, defaults, constraints, namespaces);
7 route.DataTokens["area"] = AreaName;
8
9 // disabling the namespace lookup fallback mechanism keeps this areas from accidentally picking up
10 // controllers belonging to other areas
11   bool useNamespaceFallback = (namespaces == null || namespaces.Length == 0);
12 route.DataTokens["UseNamespaceFallback"] = useNamespaceFallback;
13
14 return route;
15 }

        还有几个疑问待解决:

        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都没有错。

View Code
1 routes.Add(new Route("Index1", new MvcRouteHandler())
2 {
3 Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = UrlParameter.Optional }),
4 DataTokens = new RouteValueDictionary(new { area = "First", namespaces = new[] { "MvcAreaDemo2.Areas.First.Controllers" } })
5
6 });
7
8 routes.Add(new Route("Index2", new MvcRouteHandler())
9 {
10 Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = UrlParameter.Optional }),
11 DataTokens = new RouteValueDictionary(new { area = "Second", namespaces = new[] { "MvcAreaDemo2.Areas.Second.Controllers" } })
12
13 });


        3.在Area的使用况下,如果要跳转到另外一个Area的页面,则使用Html.ActionLink进行编写似乎更加麻烦了,有木有更加简便的方法?

        

posted @ 2011-05-10 15:40  雁北飞  阅读(1654)  评论(1编辑  收藏  举报