設定:
メニューを管理するためにmvcSiteMapProviderでASP.NETMVC4を使用しています。
ノードが現在のブランチにあるかどうかを評価するカスタムメニュービルダーがあります(つまり、SiteMap.CurrentNode
がCurrentNodeであるか、CurrentNodeがその下にネストされているかどうか)。コードは以下に含まれていますが、基本的に各ノードのURLをチェックし、現在のノードの「家系図」まで、現在のノードのURLと比較します。
CurrentBranchは、カスタムメニュービルダーによって、CurrentBranchのメニュー項目を強調表示するクラスを追加するために使用されます。
問題:
私のカスタムメニューは正常に機能しますが、が一貫した方法でのmvcSiteMapProvider
を評価していないようです。url
CurrentNode
2つのノードが同じアクションを指し、アクションのパラメーターによってのみ区別される場合、SiteMap.CurrentNodeは正しいルートを使用していないようです(区別パラメーターを無視し、デフォルトでで定義されたアクションにマップする最初のルートになります)ノード)。
問題の例:
アプリで私は持っていMembers
ます。
メンバーには、MemberStatus
「未処理」、「アクティブ」、または「非アクティブ」のフィールドがあります。MemberStatusを変更するために、私はProcessMemberController
Adminというエリアにいます。処理は、のProcess
アクションを使用して実行されProcessMemberController
ます。
私のmvcSiteMapには、両方がProcess
アクションにマップする2つのノードがあります。それらの唯一の違いはalternate
パラメーター(私のクライアントのドメインセマンティクスなど)であり、ある場合には「処理済み」の値を持ち、他の場合には「未処理」の値を持ちます。
ノード:
<mvcSiteMapNode title="Process" area="Admin" controller="ProcessMembers" action="Process" alternate="Unprocessed" />
<mvcSiteMapNode title="Change Status" area="Admin" controller="ProcessMembers" action="Process" alternate="Processed" />
ルート:
これらの2つのノードへの対応するルートは次のとおりです(ここでも、それらを区別する唯一のものは代替パラメーターの値です)。
context.MapRoute(
"Process_New_Members",
"Admin/Unprocessed/Process/{MemberId}",
new { controller = "ProcessMembers",
action = "Process",
alternate="Unprocessed",
MemberId = UrlParameter.Optional }
);
context.MapRoute(
"Change_Status_Old_Members",
"Admin/Members/Status/Change/{MemberId}",
new { controller = "ProcessMembers",
action = "Process",
alternate="Processed",
MemberId = UrlParameter.Optional }
);
何が機能するか:
Html.ActionLinkヘルパーはルートを使用し、期待するURLを生成します。
@Html.ActionLink("Process", MVC.Admin.ProcessMembers.Process(item.MemberId, "Unprocessed")
// Output (alternate="Unprocessed" and item.MemberId = 12): Admin/Unprocessed/Process/12
@Html.ActionLink("Status", MVC.Admin.ProcessMembers.Process(item.MemberId, "Processed")
// Output (alternate="Processed" and item.MemberId = 23): Admin/Members/Status/Change/23
どちらの場合も、出力は正しく、私が期待しているとおりです。
動作しないもの:
私のリクエストに2番目のオプション、つまり、/Admin/Members/Status/Change/47
alternate="Processed"と47のMemberIdに対応するオプションが含まれているとします。
静的なCurrentBranchプロパティ(以下を参照)をデバッグすると、SiteMap.CurrentNodeは次のように表示されます。
PreviousSibling: null
Provider: {MvcSiteMapProvider.DefaultSiteMapProvider}
ReadOnly: false
ResourceKey: ""
Roles: Count = 0
RootNode: {Home}
Title: "Process"
Url: "/Admin/Unprocessed/Process/47"
つまり、リクエストURLが/ Admin / Members / Status / Change / 47の場合、はにSiteMap.CurrentNode.Url
評価され/Admin/Unprocessed/Process/47
ます。つまり、alternate
パラメータを無視し、間違ったルートを使用しています。
CurrentBranch静的プロパティ:
/// <summary>
/// ReadOnly. Gets the Branch of the Site Map that holds the SiteMap.CurrentNode
/// </summary>
public static List<SiteMapNode> CurrentBranch
{
get
{
List<SiteMapNode> currentBranch = null;
if (currentBranch == null)
{
SiteMapNode cn = SiteMap.CurrentNode;
SiteMapNode n = cn;
List<SiteMapNode> ln = new List<SiteMapNode>();
if (cn != null)
{
while (n != null && n.Url != SiteMap.RootNode.Url)
{
// I don't need to check for n.ParentNode == null
// because cn != null && n != SiteMap.RootNode
ln.Add(n);
n = n.ParentNode;
}
// the while loop excludes the root node, so add it here
// I could add n, that should now be equal to SiteMap.RootNode, but this is clearer
ln.Add(SiteMap.RootNode);
// The nodes were added in reverse order, from the CurrentNode up, so reverse them.
ln.Reverse();
}
currentBranch = ln;
}
return currentBranch;
}
}
質問:
私は何が間違っているのですか?
ルートは、期待どおりにHtml.ActionLlinkによって解釈されますが、期待どおりにSiteMap.CurrentNodeによって評価されません。つまり、ルートを評価する際に、SiteMap.CurrentNodeは識別可能な代替パラメーターを無視します。