zoukankan      html  css  js  c++  java
  • 在ASP.Net MVC 中,如何在Global.asax中配置一个指向Area内部的默认Route

    ASP.Net MVC 中配置Route的时候可以设置一个默认的Route。

    比如我要在输入http://localhost的时候默认进入http://localhost/home/index。可以在Global.asax中这么配置:

    C#代码  收藏代码
    routes.MapRoute(  
        "Default", // Route name  
        "{controller}/{action}/{id}", // URL with parameters  
        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults  
    );  

    很简单,对吧。

    但是如果你想把默认值指向一个Area内部的Controller/Action,要怎么做呢? 

    模仿上面的例子,我是这么做的:

    新建一个叫做MyArea的area,然后配置路由如下:

    C#代码  收藏代码
    routes.MapRoute(  
        "Default", // Route name  
        "{area}{controller}/{action}/{id}", // URL with parameters  
        new {area = "MyArea", controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults  
    );  

    添加了一个area的section,应该可以了吧。

    运行一下看看:

    结果是Controller冲突,截图如下:



     

    这说明了我们配置的那个{Area}没起作用。原来MVC的route没有对Area进行支持。

    来看看MyAreaAreaRegistration的源码中是怎么做的:

    C#代码  收藏代码
    public Route MapRoute(string name, string url, object defaults, object constraints, string[] namespaces) {  
        if (namespaces == null && Namespaces != null) {  
            namespaces = Namespaces.ToArray();  
        }  
      
        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;  
    }  

     它在MapRoute的时候加入了一个namespace的约束。那我们也来加上看看。

    C#代码  收藏代码
    routes.MapRoute(  
               "Default", // Route name  
               "{controller}/{action}/{id}", // URL with parameters  
               new {controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults  
               new[] { "WebArchDemo.Areas.MyArea.*" }    
           );  

     OK,成功了。不过仔细一看。View不对了。它竟然还是去找Area外面的View,而不是这个Area下面的View.

     我们在ViewEngine的源码中找一下原因,关键代码是在寻找View时的下面几句:

    C#代码  收藏代码
    string areaName = AreaHelpers.GetAreaName(controllerContext.RouteData);  
    bool usingAreas = !String.IsNullOrEmpty(areaName);  
    List<ViewLocation> viewLocations = GetViewLocations(locations, (usingAreas) ? areaLocations : null);  

     ViewEngine会在controllerContext.RouteData中去找AreaName,如果找到的话就用Area中的View,否则用根目录下的View.那这个AreaName是什么时候放如RouteData中的呢?

    回头看一下我前面贴出来那段MyAreaAreaRegistration中的源码,关键的一句就是:

    C#代码  收藏代码
    route.DataTokens["area"] = AreaName; 

    就是在注册Area的Route的时候,会把这个AreaName放进去。

    明白了这一点,我们就可以来继续改造我们注册route的地方:

    C#代码  收藏代码
             var route =   routes.MapRoute(  
                                   "Default", // Route name  
                                   "{controller}/{action}/{id}", // URL with parameters  
                                   new {controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults  
                                   new[] { "WebArchDemo.Areas.MyArea.*" }    
                               );  
      
    route.DataTokens["area"] = "MyArea";  

    测试一下,完全正确。

    在实际的项目中,可能直接把默认route指向Area内部的一个Action的几率比较小。不过还是有一些特殊场景。

    我们通过尝试来实现这么一种特殊场景,分析了AreaRegistration的工作原理,也窥探了一下Route和ViewEngine是如何处理Area的。

    我们可以看到,MVC在尽可能少地侵入框架的情况下,实现了一套Area机制。

  • 相关阅读:
    Kubernetes+Federation打造跨多云管理服务
    idou老师教你学istio 31:Istio-proxy的report流程
    《软件工程》课程总结(补)
    《软件工程》课程总结
    十二周# 学习进度总结
    十一周# 学习进度总结
    十周# 学习进度总结
    九周# 学习进度总结
    八周# 学习进度总结
    团队项目——编写项目的Spec
  • 原文地址:https://www.cnblogs.com/cyccess/p/3142185.html
Copyright © 2011-2022 走看看