ASP.NET MVC开发专题博客

ASP.NET MVC开发专题博客,为您精选ASP.NET MVC开发教程,助您开发愉快!

公告信息
欢迎光临ASP.NET MVC开发专题博客,祝您开发愉快!
文章档案
最新评论

ASP.NET MVC路由机制扩展及Area原理-MVC原理系列4


上节:MVC URL outbound原理及URL优化设计-MVC原理系列3,我们讲解了如何自定义URL及从SEO角度进行SEO优化设计URL。

本节,我们来了解一下:ASP.NET MVC的Area机制,同时实现自定义的MVC路由机制扩展。

下面且看正文:


ASP.NET MVC DataTokens和Areas机制

到目前为止Route对象只剩下DataTokens属性没有涉及,事实上这个Areas机制的核心。

DataTokens实际上也是一个RouteValueDictionary,在用MapRoute方法构造在Route构造的时候,可以传一个namespaces字符串数组,这个参数会构造成Route对象的DataTokens["Namespaces"],它的值将被MVC框架优先用来在对应的名字空间中查找相应的Controller。如果在指定的名字空间中能找到Controller,那么,就算在其他名字空间中有相同名字的Controller(大小写敏感)也没关系;如果在指定的名字空间中没有找到Controller,那么将在所有引用的程序集中查找,此时如果出现重复名字的Controller,那么将出现多个匹配的错误。这种行为是DefaultControllerFactory实现的,关于DefaultControllerFactory将在以后分析。

Areas机制是这样的一种机制:在不同的Area中可以有相同名字的Controller,也就是说Controller的名字可以重复了!这样整个web应用程序可以按功能划分成几个模块,每个模块是一个Area,每个Area互相独立,可以独立地由某个开发人员随意定义URL或Controller而不影响其他Area。

比如:有管理员和用户两个模块,也许需要如下的URL:

Admin/Home/Index

User/Home/Index

于是可以用VS集成的Area生成模板创建两个Area:Admin和User,分别地,由两个开发人员分别负责开发,他们都需要用HomeController和Index方法,有了Areas机制,HomeController被分别放到两个不同的名字空间中,这就不会有冲突。

讲到这里你也许隐约明白DataTokens和Areas机制的某种关系了。在vs创建Areas的时候到底做了哪些事情呢?

一、首先在每个Area中Controller都将被放置到一个名字空间中,例如:MyAppName.Areas.Admin.Controllers;

二、为每个Area创建一个AreaRegistration的继承类,如果是Admin的Area将是AdminAreaRegistration。在这个类中重写AreaName属性和RegisterArea方法:

1public override void RegisterArea(AreaRegistrationContext context)
2{
3    context.MapRoute(
4        "Admin_default",
5        "Admin/{controller}/{action}/{id}",
6        new { action = "Index", id = UrlParameter.Optional }
7    );
8}

可以看到在RegisterArea方法中也调用了MapRoute方法注册路由。需要注意的是这个的MapRoute虽然也是操作全局路由表,但是它的实现略有不同:

1.首先设置的URL Pattern是以Area名字开头的,这样做是必要的,毕竟这个URL Pattern最终是放在全局中的;

2.它会将DataTokens["Namespaces"]设置成当前Area的名字空间,比如MyAppName.Areas.Admin.*。结果是,当一个请求到来是,DefaultControllerFactory会优先到这个名字空间下查找Controller。而且会增加一个DataTokens["UseNamespaceFallback"],并设置为false,这样当且仅当显示设置的名字空间中有需要的Controller时,才能成功,其他名字空间的的同名Controller将无效;

3.最后,还会添加一个叫DataTokens["area"]的键值,并设置为当前Area名字,这是为了在反向映射(outbounding)URL的时候使用。因此在MVC中"area"键是有特殊用途的,所以不能用于url pattern的参数。

在Areas机制中有一个冲突需要注意。由于路由表只有一张,如果当前的url映射到了"root area"(即在Global域),那么将从当前所有的名字空间中查找Controller,此时很可能找到多个匹配的。解决方案是,在Globla.asax.cs中设置路由的时候,为DataTokens设置优先名字空间。

 

 

 进一步ASP.NET MVC扩展

当从深层次了解了路由工作机制后,就进行一些自定义了。

自定义RouteBase

有前面的分析,可以知道,在inbound时Route(继承自RouteBase)需要提供一个RouteData,因此RouteBase定义了GetRouteData方法,这是我们可以自己实现的;同时,GetVirtualPath方法用于outbound。所以,只要实现了这两个方法就可以完成一个RouteBase的实现。比如:当想要把一个老的网站改造成新的基于MVC架构的,又不想使原来的url失效,简单的处理方案可以像下面这样:

01public class LegacyUrlsRoute : RouteBase
02{
03    // In practice, you might fetch these from a database
04    // and cache them in memory
05    private static string[] legacyUrls = new string[] {
06    "~/articles/may/zebra-danio-health-tips.html",
07    "~/articles/VelociraptorCalendar.pdf",
08    "~/guides/tim.smith/BuildYourOwnPC_final.asp"
09    };
10    public override RouteData GetRouteData(HttpContextBase httpContext)
11    {
12        string url = httpContext.Request.AppRelativeCurrentExecutionFilePath;
13        if(legacyUrls.Contains(url, StringComparer.OrdinalIgnoreCase)) {
14            RouteData rd = new RouteData(thisnew MvcRouteHandler());
15            rd.Values.Add("controller""LegacyContent");
16            rd.Values.Add("action""HandleLegacyUrl");
17            rd.Values.Add("url", url);
18            return rd;
19        }
20        else
21        return null// Not a legacy URL
22    }
23    public override VirtualPathData GetVirtualPath(RequestContext requestContext,
24        RouteValueDictionary values)
25    {
26        // This route entry never generates outbound URLs
27        return null;
28    }
29}

 

MVC中自定义IRouteHandler

通常在MVC框架中IRouteHandler由MvcRouteHandler实现,这个MVC框架的入口。尽管如此,我们还是可以自己定义一个IRouteHandler。当我们需要对某些请求做优化处理的时候可以考虑这样做。因为,自定义实现IRouteHandler意味着将忽略MVC框架。比如下面这个实现:

01public class HelloWorldHandler : IRouteHandler
02{
03    public IHttpHandler GetHttpHandler(RequestContext requestContext)
04    {
05        return new HelloWorldHttpHandler();
06    }
07    private class HelloWorldHttpHandler : IHttpHandler
08    {
09        public bool IsReusable { get return false; } }
10        public void ProcessRequest(HttpContext context)
11        {
12            context.Response.Write("Hello, world!");
13        }
14    }
15}


本节:ASP.NET MVC路由机制扩展及Area原理-MVC原理系列4,就为您讲述到这里了,谢谢!

如果涉及数据库操作,推荐一款配套的ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"

2011/9/8 0:11:14 | ASP.NET MVC教程 | |

#1游客[注册][118.249.192.*]2012/3/25 19:07:47
MyAppName.Areas.Admin.* 其实这样解决不了问题,
注册路由时主要是想实现泛路由功能, 命名空间这又不允许使用规则进行替换, 比较头疼
  • 发表评论