Route学习笔记之Area的Route注册

前一段时间接触了MVC的Area能够将模型、控制器和视图分红各个独立的节点。分区以后,区域路由注册的需求就出来了。html

默认的编程

在MVC项目上右键添加区域以后,在文件夹下会自动添加一个FolderNameAreaRegistration.cs的文件。mvc

复制代码
public class AdminAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "Admin";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "Admin_default",
            "Admin/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional }
        );
    }
}
复制代码

在其中,定义了一个继承AreaRegistration的类,类下面 重写了AreaName和RegisterArea。固然,这一串代码已经能够很好的解决区域的路由注册问题了。asp.net

可是对于这重复的代码有点排斥,另外一个也想看看有没有其余的替换方式。ide

想看看能不能在路由注册那里统一管理函数

插曲一工具

以前在开始接触分区的时候,碰到过区域下页面的layout连接错误的问题,后来的解决方式是在ActionLink的routeValue参数里面定义area=""。this

状况和这里的有点像,不一样的是,上面的须要清除area,这里须要添加area。url

插曲二spa

最近在看《asp.net mvc4高级编程》这本书,接触到一个颇有用的工具RouteDebugger。

过程一

路由注册那里,调用的是routes.MapRoute函数,来向RouteTable.Routes中添加route。这个函数有好几个扩展,结合上面插曲一的思路,在扩展函数的defaults里面,尝试添加属性area="Test":

routes.MapRoute(
   name: "Test_Default",
   url: "Test/{controller}/{action}/{id}",
   defaults: new { area = "Test", controller = "AAA", action = "Index", id = UrlParameter.Optional },
   namespaces: new string[] { "MVCTest.Areas.Test.Controllers" });

调试经过RouteDebugger看:

输入/Test/AAA/Index,页面报错,此路不通。

过程二

同事研究这块时,发现除了默认AreaRegistration类之外的方法:

[RouteArea("Admin")]
[RoutePrefix("Test")]
[Route("{action=index}")]
public partial class TestController : Controller
{
}

在区域下的Controller上面添加Route相关特性。主要就三个:Route、RouteArea和RoutePrefix。第一个定义Area,第二个定义Controller,第三个定义默认action值为index。实际调试后,发现前台准确的匹配到了路由,思路OK

到此,结合RouteDebugger,再调试到前台,咱们能够看到:

从这个图能够看出,MapRoute的数据定义了Url、Defaults和Constraints,后面的DataTokens不能经过MapRoute函数里面传入。

查看源代码:

复制代码
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
{
    if (routes == null)
    {
        throw new ArgumentNullException("routes");
    }
    if (url == null)
    {
        throw new ArgumentNullException("url");
    }

    Route route = new Route(url, new MvcRouteHandler())
    {
        Defaults = CreateRouteValueDictionaryUncached(defaults),
        Constraints = CreateRouteValueDictionaryUncached(constraints),
        DataTokens = new RouteValueDictionary()
    };

    ConstraintValidation.Validate(route);
    if ((namespaces != null) && (namespaces.Length > 0))
    {
        route.DataTokens[RouteDataTokenKeys.Namespaces] = namespaces;
    }
    routes.Add(name, route);
    return route;
}
复制代码

注意,上面的DataTokens是new了一个RouteValueDictionary对象。

而想要注入的area数据正是在DataTokens里面。因此上面的第一次尝试失败,是由于数据注入到了Defaults里面。

到了这里,怎么在RegisterRoutes里面统一管理区域的路由注册,思路已经呼之欲出了。

解决方案:

routes.Add(new Route("PaperMaster/{controller}/{action}/{id}"
    , new RouteValueDictionary(new { controller = "Papers", action = "Index", id = UrlParameter.Optional })
    , new RouteValueDictionary()
    , new RouteValueDictionary(new { area = "PaperMaster", namespaces = "Packmage.Web.Areas.PaperMaster.Controllers" })
    , new MvcRouteHandler()));

直接实例化Route对象,输入它的各个须要的属性;不用MapRoute,改用Add,直接向RouteTable.Routes中添加route对象。

相关文章
相关标签/搜索