您的位置:首页 > 编程语言 > ASP

ASP.NET MVC - Area的路由映射(使用NampSpace)

2016-11-27 16:34 441 查看
在开始之前,首先来看2个问题。

如果有一个Area叫Database,在它的下面有一个Controller名字叫做Browse。

另外我在顶层也有一个Controller,名字也叫Browse。

NameSpace结构如下:

MvcApplication.Controllers.BrowseController

MvcApplication.Areas.Database.Controllers.BrowseController

路由注册信息如下:

[csharp] view
plain copy

public static void RegisterRoutes(RouteCollection routes)  

{  

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  

  

    routes.MapRoute(  

        "Default", // Route name  

        "{controller}/{action}/{id}", // URL with parameters  

        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults  

    );  

  

}  

[csharp] view
plain copy

namespace MvcApplication.Areas.Database  

{  

    public class DatabaseAreaRegistration : AreaRegistration  

    {  

        public override string AreaName  

        {  

            get  

            {  

                return "Database";  

            }  

        }  

  

        public override void RegisterArea(AreaRegistrationContext context)  

        {  

            context.MapRoute(  

                "Database_default",  

                "Database/{controller}/{action}/{id}",  

                new { action = "Index", controller = "Browse", id = UrlParameter.Optional }  

            );  

        }  

    }  

}  

问题1:当我输入: http://localhost/Browse的时候,会出现什么情况?
问题2:当我输入: http://localhost/Database/Browse的时候,又会出现什么情况。
输入http://localhost/Browse,我们得到的将是一个异常: Multiple types were found that match the controller named 'Browse'. 

而输入http://localhost/Database/Browse,我们却能够正常地访问到 MvcApplication.Areas.Database.Controllers.BrowseController。

如果看过DefaultControllerFactory源代码的同学,对于第一个问题不难理解,在有Controller同名的情况下(虽然是在不同的命名空间),会发生异常并不奇怪,但是为何在Area中却没有任何冲突呢?

乍一看,两者的路由注册并没有太多的不同,为什么结果却截然不同呢?

如果认为顶层路由映射和Area路由映射没有太多不同的话,那可就要被骗喽。

实际上,两者用的函数名确实是一样的,但是顶层用到的是RouteCollection去MapRoute,而在Area中,用的确实AreaRegistrationContext去MapRoute。

由此可以猜想,这个不老实的AreaRegistrationContext肯定在背后偷偷摸摸干了些什么事情。

在看了一下的源码之后发现,这个事情并不是由AreaRegistrationContext单独完成,AreaRegistration也牵涉其中:

[csharp] view
plain copy

namespace System.Web.Mvc  

{  

    public abstract class AreaRegistration  

    {  

        private const string TypeCacheName = "MVC-AreaRegistrationTypeCache.xml";  

  

        public abstract string AreaName { get; }  

  

        internal void CreateContextAndRegister(RouteCollection routes, object state)  

        {  

            AreaRegistrationContext context = new AreaRegistrationContext(AreaName, routes, state);  

  

            string thisNamespace = GetType().Namespace;  

            if (thisNamespace != null)  

            {  

                context.Namespaces.Add(thisNamespace + ".*");  

            }  

  

            RegisterArea(context);  

        }  

  

<span style="white-space:pre">  </span>// ...  

    }  

}  

[csharp] view
plain copy

namespace System.Web.Mvc  

{  

    public class AreaRegistrationContext  

    {  

<span style="white-space:pre">  </span>// ...  

        public Route MapRoute(string name, string url, object defaults, object constraints, string[] namespaces)  

        {  

            if (namespaces == null && Namespaces != null)  

            {  

                namespaces = Namespaces.ToArray(); // 如果没有填写命名空间,则使用Area所在的命名空间  

            }  

  

            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;  

        }  

    }  

}  

从上述源码中可以看出,在注册Area的路由时,如果没有填写命名空间的话,则会默认使用Area所在的命名空间。如此一来,使用Area的路由在寻找Controller时,只会在Area所在的空间下寻找相应的Controller,那就不存在与顶层Controller的冲突问题了,可是顶层的同名Controller问题如何解决呢,这个好办,在顶层路由映射的时候主动加上命名空间吧,这样子就皆大欢喜,你用你的Browse,我用我的Browse,互不相干。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  asp.net mvc namespace