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,互不相干。
如果有一个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 - Area的路由映射(使用NampSpace)
- ASP.NET MVC - Area的路由映射(使用NampSpace)
- 填充区域 (Populating an Area) | 使用区域 | 高级路由特性 | 精通ASP-NET-MVC-5-弗瑞曼
- 创建一个区域(Creating an Area) |使用区域 | 高级路由特性 | 精通ASP-NET-MVC-5-弗瑞曼
- ASP.NET MVC Area使用-将Area设置成独立项目
- 认识 ASP.NET 3.5 MVC 路由 在WebForm项目中使用路由
- 在ASP.NET MVC中使用Area
- ASP.NET MVC- Area 使用
- asp.net mvc设置area页面为默认路由
- [转]Asp.net MVC 3使用 Area 小结
- 在ASP.NET MVC中使用正则表达式定义路由(翻的)
- [ASP.NET MVC 小牛之路]08 - Area 使用
- 《Entity Framework 6 Recipes》中文翻译系列 (21) -----第四章 ASP.NET MVC中使用实体框架之在页面中创建查询和使用ASP.NET URL路由过虑
- [ASP.NET MVC 小牛之路]08 - Area 使用
- [ASP.NET MVC 小牛之路]08 - Area 使用
- 使用asp.net mvc里面的area让网站更有条理
- ASP.NET MVC路由扩展:路由映射
- 初识ASP.NET 3.5 MVC 路由 在WebForm项目中使用路由
- asp.net web form 使用URL路由 注不是mvc中的路由
- ASP.NET MVC路由扩展:路由映射