• Route学习笔记之Area的Route注册


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

    默认的

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

    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。当然,这一串代码已经可以很好的解决区域的路由注册问题了。

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

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

    插曲一

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

    情况和这里的有点像,不同的是,上面的需要清除area,这里需要添加area。

    插曲二

    最近在看《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对象。

    到此问题解决。留文备用。

    PS:以前做winform没有怎么接触.net的源码,现在研究asp.net,开源的模块比较多,越来越多的接触.net的源码,感觉读源码非常重要,也非常有用。能够更加清晰的知道自己的代码在干什么,遇到问题,可以通过查看本质而去寻求直接有效的解决方法,效率也高很多。

  • 相关阅读:
    js基础学习
    线程安全与锁
    JS浏览器检测工具方法、url参数读取
    【转载】JS时间工具类收藏(时间转换、倒计时)
    使用JQuery插件Jcrop进行图片截取
    记录小文件上传的几个例子(含进度条效果,附源码下载)
    T-SQL分页查询语句
    记录JavaScript中使用keyup事件做输入验证(附event.keyCode表)
    知识记录:ASP.NET 应用程序生命周期概述及Global.asax文件中的事件
    记录FormsAuthentication的使用方法
  • 原文地址:https://www.cnblogs.com/icyJ/p/AreaRegister.html
Copyright © 2020-2023  润新知