web-dev-qa-db-ja.com

RouteDataからルート名を取得するにはどうすればよいですか?

Global.asaxでいくつかのルートを定義しています。

ページにいるとき、現在のルートのルート名が何であるかを理解する必要があります。これは、ルート名が私のサイトメニューを制御するためです。

これはどのように行うことができますか?

33
Andrey

残念ながら、ルートの名前はルートのプロパティではないため、ルートの名前を取得することはできません。 RouteTableにルートを追加するとき、名前はルートの内部インデックスとして使用され、公開されることはありません。

これを行う方法は1つあります。

ルートを登録するとき、ルートにDataTokenを設定し、ルート名を使用してルートをフィルタリングします。

#1を行う最も簡単な方法は、おそらくルートをマッピングするための独自の拡張メソッドを記述することです。

23
Haacked

あなたがチェックする必要がある重要なルートの小さなサブセットで作業している場合(特別なケースか2つ)、これを行うことができます:

if (routeData.Route == RouteTable.Routes["gallery-route"])
{
   // current route is 'gallery-route'
}

ルート名が必要になる一般的な理由は、デバッグのためです。これをすばやく簡単に行う方法は次のとおりですが、名前の配列に各ルート名を追加する必要があります。特にコードが本番稼働中に実行されていない場合は、デバッグには問題ありません。

// quick and dirty way to get route name
public string GetRouteName(RouteData routeData) 
{
    foreach (string name in new [] { "gallery-route", 
                                     "products-route", 
                                     "affiliate-route", 
                                     "default" }) 
    {
        if (routeData.Route == RouteTable.Routes[name])
        {
            return name;
        }
    }
    return "UNKNOWN-ROUTE";   // or throw exception
}

これを超えるものについては、@ haackedのソリューションに必要な(最小限の)時間を取る必要があります。

11
Simon_Weaver

FWIW、@ Simon_Weaverによって示される拡張機能と例はMVCベースであり、投稿にはWebFormsのタグが付けられているため、私のWebFormsベースの拡張メソッドを共有すると思いました。

    public static void MapPageRouteWithName(this RouteCollection routes, string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess = true,
            RouteValueDictionary defaults = default(RouteValueDictionary), RouteValueDictionary constraints = default(RouteValueDictionary), RouteValueDictionary dataTokens = default(RouteValueDictionary))
    {
        if (dataTokens == null)
            dataTokens = new RouteValueDictionary();

        dataTokens.Add("route-name", routeName);
        routes.MapPageRoute(routeName, routeUrl, physicalFile, checkPhysicalUrlAccess, defaults, constraints, dataTokens);
    }

    public static string GetRouteName(this RouteData routeData) 
    {
        if (routeData.DataTokens["route-name"] != null)
            return routeData.DataTokens["route-name"].ToString();
        else return String.Empty;
    }

ルートを登録するときは、routes.MapPageRoute(...)のようにする代わりに、Global.asax.csを使用します。代わりに、拡張メソッドを使用して、routes.MapPageRouteWithName(...)を実行します。

次に、現在の経路を確認する場合は、Page.RouteData.GetRouteName()を実行します。

それでおしまい。リフレクションはありません。「route-name」へのハードコードされた参照は、2つの拡張メソッドのみです(本当に必要な場合は、constで置き換えることができます)。

10
kman

これが@haackedの提案の実装です。ルートデータを表示するための単純な「かみそり」テーブルもあります。

注:すべての標準の「MapRoute」メソッドが実際には拡張メソッドであることに気付いていない可能性があります。したがって、同じ名前を使用することはできません。たった今それを「MapRoute2」と呼んでいます。なぜなら、今のところそれが私が考えることができるすべてだからです。

MapRouteへのすべての呼び出しをMapRoute2への呼び出しに置き換える必要があります。すべてのAreaRegistrationファイルとglobal.asax.csを忘れないでください

拡張メソッド:

public static class RouteNameExtensions
{
    // RouteCollection
    public static Route MapRoute2(this RouteCollection routes, string name, string url)
    {
        return AddRouteNameDataToken(name, routes.MapRoute(name, url));
    }

    public static Route MapRoute2(this RouteCollection routes, string name, string url, object defaults)
    {
        return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults));
    }

    public static Route MapRoute2(this RouteCollection routes, string name, string url, string[] namespaces)
    {
        return AddRouteNameDataToken(name, routes.MapRoute(name, url, namespaces));
    }

    public static Route MapRoute2(this RouteCollection routes, string name, string url, object defaults, object constraints)
    {
        return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults, constraints));
    }

    public static Route MapRoute2(this RouteCollection routes, string name, string url, object defaults, string[] namespaces)
    {
        return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults, namespaces));
    }

    public static Route MapRoute2(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
    {
        return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults, constraints, namespaces));
    }

    // AreaRegistrationContext
    public static Route MapRoute2(this AreaRegistrationContext routes, string name, string url)
    {
        return AddRouteNameDataToken(name, routes.MapRoute(name, url));
    }

    public static Route MapRoute2(this AreaRegistrationContext routes, string name, string url, object defaults)
    {
        return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults));
    }

    public static Route MapRoute2(this AreaRegistrationContext routes, string name, string url, string[] namespaces)
    {
        return AddRouteNameDataToken(name, routes.MapRoute(name, url, namespaces));
    }

    public static Route MapRoute2(this AreaRegistrationContext routes, string name, string url, object defaults, object constraints)
    {
        return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults, constraints));
    }

    public static Route MapRoute2(this AreaRegistrationContext routes, string name, string url, object defaults, string[] namespaces)
    {
        return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults, namespaces));
    }

    public static Route MapRoute2(this AreaRegistrationContext routes, string name, string url, object defaults, object constraints, string[] namespaces)
    {
        return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults, constraints, namespaces));
    }

    private static Route AddRouteNameDataToken(string name, Route route)
    {
        route.DataTokens["route-name"] = name;
        return route;
    }
}

ルーティング情報を表示するために使用している簡単なかみそり.cshtmlファイルは次のとおりです。

<table class="basic-table">
    <tr>
        <th>Route Key</th>
        <th>Value</th>
    </tr>

    <tr>
        <td><strong>Route name</strong></td>
        <td>@ViewContext.RouteData.DataTokens["route-name"]</td>
    </tr>

    @foreach (var route in ViewContext.RouteData.Values)
    {
        <tr>
            <td>- @route.Key</td>
            <td>@(route.Value ?? "<null>")</td>
        </tr>
    }
    @foreach (var route in ViewContext.RouteData.DataTokens.Where(x=>x.Key != "route-name"))
    {
        <tr>
            <td><strong>@route.Key</strong></td>
            <td>@(route.Value ?? "<null>")</td>
        </tr>
    }

</table>
7
Simon_Weaver

私はSimon_Weaverの回答に賛成票を投じますが、残念ながら参加したばかりで、そのための評判ポイントがありません。

彼の答えに加えて、それがまさに私が探していたものだったので、ここに私がそれをする方法があります:

私はパブリック列挙型「PageRouteTable」を持っています:

public enum PageRouteTable
{
    // -- User Area
    UserArea_Locations,
    UserArea_Default,
    UserArea_PasswordReset,
    UserArea_Settings,
    .
    .
    .
}

ルートを構築するときにこの列挙型を使用します。

/* -- User Area Routes -- */
routes.MapPageRoute(PageRouteTable.UserArea_Default.ToString(), "home", "~/UserArea/Default.aspx");

次に、ページ拡張メソッドを作成しました。

public static PageRouteTable? CurrentRoute(this Page p)
{
    string[] pageRoutes = Enum.GetNames(typeof (PageRouteTable));
    foreach (string pageRoute in pageRoutes)
    {
        if (p.RouteData.Route == RouteTable.Routes[pageRoute])
        {
            return (PageRouteTable)Enum.Parse(typeof (PageRouteTable), pageRoute);
        }
    }
    return null;
}

これで、私のページでは、スイッチを使用してそれに作用することができます。

PageRouteTable? currentRoute = this.CurrentRoute();
if (currentRoute.HasValue) {
    switch(currentRoute.Value) {
        case PageRouteTable.UserArea_Default:
            // Act accordingly
            break;
        .
        .
        .
    }
}

また、明示的に定義された変数の利点があり、文字列に対するコーディングについて心配する必要はありません。これにより、メンテナンスにかかる頭痛の種を大幅に減らすことができます。

-幸せなコーディング。

6
MikeAtCodeSmart

RouteCollection 名前付きルートのプライベートディクショナリを維持します。

ルート名はそれによってそれから同軸化することができます

  1. リフレクションを使用してプライベートフィールドの値を取得し、
  2. ルートが値であるアイテムの辞書をクエリします。

以下の拡張メソッドは、このプロセスに従います。

public static string Name(this RouteBase original)
{
    var routes = System.Web.Routing.RouteTable.Routes;

    if (routes.Contains(original))
    {
        var namedMapField = routes.GetType().GetField("_namedMap", BindingFlags.NonPublic | BindingFlags.Instance);
        var namedMap = namedMapField.GetValue(routes) as Dictionary<string, RouteBase>;

        var query = 
            from pair in namedMap 
            where pair.Value == original 
            select pair.Key;

        return query.Single();
    }

    return string.Empty;
}
3
Samu Lang

C#の場合、次のようにルートを宣言できます。

        routeCollection.MapPageRoute("RouteForProduct", "Product/{ProductName}", "~/IRShop.aspx", false, new RouteValueDictionary { { "Section", "product" } });
        routeCollection.MapPageRoute("RouteForProductList", "ProductList/{CatName}", "~/IRShop.aspx", false, new RouteValueDictionary { { "Section", "productlist" } });
        routeCollection.MapPageRoute("RouteForContentList", "Content/{PageName}", "~/IRShop.aspx", false, new RouteValueDictionary { { "Section", "content" } });

次に、ルートが必要なメソッドで、次を呼び出すことができます。

var x = Page.RouteData.Values["Section"].ToString();

そして、global.asaxに文字列を設定し、必要に応じて使用します。

2
Andrew Berry

私は同じジレンマに直面しており、残念ながら、ASP.NETがどのルート(その名前)を使用するために選択したのかを見つける方法はないようです。

あなたはあなたのルートに存在するかもしれないパラメータの名前によってそれを理解することしかできないようです-それらはRouteData.Values辞書に表示されます。

特定のURLに対してASP.NETによって選択されたルートの実際の名前に何らかの方法でアクセスする方法を誰かが知っている場合は、自分でもその方法を知りたいと思います。

1
marc_s

すべてのルートパラメータを追加できますが、必須ではありませんが、このパラメータはURLに含める必要があります。ルート名を次のようなパラメータとしてグローバルに割り当てることができます。

 routes.MapPageRoute("Page",
                "Page-{ID}",
               "~/Item_show.aspx", false, new RouteValueDictionary{ { "RouteName" , "Page" }});

そして、あなたのページでそれにアクセスします:

if (RouteData.Values["RouteName"] != null)
           {
               if (RouteData.Values["RouteName"].ToString() == "Page")
               {
                   Response.Write(RouteData.Values["RouteName"]);

               }  

           }

最善の方法は難しい方法ではありません。

1
Farhawd

私が実装した簡単なアプローチは、.MapPageRouteメソッドの 'defaults'パラメータに名前付きキーを提供することです。デフォルトには定数を使用します。通常と同じ方法で、Page.RouteData.Valuesコレクションから定数を引き出すことができます。

例(vb.net)

_routes.MapPageRoute("league-division-stats", "{league}/{division}/stats", "~/routes/league-division-stats.aspx", False, New RouteValueDictionary(New With {.section = "stats"}))
_

Page.RouteData.Values("section")は 'stats'をくれます

0
ScottE