zoukankan      html  css  js  c++  java
  • 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 }
                );
            }
    View Code

           当调用 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);
                }
            }
    View Code

           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);
            }
    View Code

          各个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;
            }
    View Code

            还有几个疑问待解决:

            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" } })
    
                });
    View Code

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

    明确个目标,一直走下去
  • 相关阅读:
    题目:有一对兔子,从出生第三个月起每个月都生一对兔子,小兔子长到第三个月后,每个月又生一对兔子,假如兔子都不死,问M个月时兔子的数量,M为键盘读入的正整数。(请用java语言作答)
    无聊游戏随笔--学院篇
    Java数组冒泡,选择,插入三种常用排序法及自带的快速排序法
    js写年月日三级下拉列表框
    查询避免Unknown column ‘xxx’ in ‘where clause’
    MyEclipse运行web程序报错,先检查这几点!
    Servlet开发之中线程安全问题
    取消Eclipse等号、分号、空格代码自动补全
    try/catch、finally语句的执行顺序测试
    02-MySQL双机热备的搭建
  • 原文地址:https://www.cnblogs.com/fhlj/p/3615244.html
Copyright © 2011-2022 走看看