Global.asaxでいくつかのルートを定義しています。
ページにいるとき、現在のルートのルート名が何であるかを理解する必要があります。これは、ルート名が私のサイトメニューを制御するためです。
これはどのように行うことができますか?
残念ながら、ルートの名前はルートのプロパティではないため、ルートの名前を取得することはできません。 RouteTableにルートを追加するとき、名前はルートの内部インデックスとして使用され、公開されることはありません。
これを行う方法は1つあります。
ルートを登録するとき、ルートにDataTokenを設定し、ルート名を使用してルートをフィルタリングします。
#1を行う最も簡単な方法は、おそらくルートをマッピングするための独自の拡張メソッドを記述することです。
あなたがチェックする必要がある重要なルートの小さなサブセットで作業している場合(特別なケースか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のソリューションに必要な(最小限の)時間を取る必要があります。
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で置き換えることができます)。
これが@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>
私は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;
.
.
.
}
}
また、明示的に定義された変数の利点があり、文字列に対するコーディングについて心配する必要はありません。これにより、メンテナンスにかかる頭痛の種を大幅に減らすことができます。
-幸せなコーディング。
RouteCollection 名前付きルートのプライベートディクショナリを維持します。
ルート名はそれによってそれから同軸化することができます
以下の拡張メソッドは、このプロセスに従います。
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;
}
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に文字列を設定し、必要に応じて使用します。
私は同じジレンマに直面しており、残念ながら、ASP.NETがどのルート(その名前)を使用するために選択したのかを見つける方法はないようです。
あなたはあなたのルートに存在するかもしれないパラメータの名前によってそれを理解することしかできないようです-それらはRouteData.Values
辞書に表示されます。
特定のURLに対してASP.NETによって選択されたルートの実際の名前に何らかの方法でアクセスする方法を誰かが知っている場合は、自分でもその方法を知りたいと思います。
すべてのルートパラメータを追加できますが、必須ではありませんが、このパラメータは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"]);
}
}
最善の方法は難しい方法ではありません。
私が実装した簡単なアプローチは、.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'をくれます