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的源碼,感覺讀源碼非常重要,也非常有用。能夠更加清晰的知道自己的代碼在干什么,遇到問題,可以通過查看本質而去尋求直接有效的解決方法,效率也高很多。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM