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對象。

相關文章
相關標籤/搜索