13

私が取り組んでいるWebサイトには、かなり複雑なルーティング構造があり、ルーティングエンジンを使用して、必要な方法でURLを構築するのに問題が発生しています。

正規表現ベースのパターンマッチングを使用して複数の変数を単一のルートセグメントにグループ化する検索結果ページがあります(つまり、「www.host.com/{structuralParameters}」は次のようになります:「www.host.com/variableA-variableB- variableC "-変数AからCはすべてオプションです)。これは少しの作業の後、私たちのためにうまく機能しています。

私たちが経験している問題は、ActionLinkメソッドの厄介な機能の周りで解決されます。同じコントローラー/アクションをポイントすると、必要かどうかに関係なく、既存のルート値が保持されます。リンクがどのように表示されるかを制御することを好み、場合によっては、既存のパラメーターを保持することはできません。例としては、サイトのメインナビゲーションが、パラメータが設定されていない検索結果ページにつながる場合があります。必要に応じて、デフォルトの検索ページです。これは、ASP.Net MVC Frameworkのまれなインスタンスであり、明確な拡張ポイントのない実装を指示しているように見えるため、これは厄介な機能だと思います。マスターページに単純なナビゲーションリンクを書き込むためのカスタムActionLinkコードを作成したくないのです。

このようなパラメータを明示的に空の文字列に設定する必要があると言う人もいますが、これを試してみると、パラメータがルート値からクエリ文字列パラメータに変更されるだけです。ActionLinkメソッドにパラメーターとして明示的に渡していない値を明示的に除外する必要があるとは思えませんが、これが唯一のオプションである場合は、それを使用します。ただし、現時点では、クエリ文字列に表示されている場合は、パラメータをルートに直接配置するのと同じくらい役に立ちません。

私たちのルーティング構造がこの問題を悪化させていることを私は知っています-より単純なアプローチ(すなわちwww.host.com/variableA/variableB/variableC)を使用した場合、おそらく問題はありませんが、URL構造は交渉可能ではありません-それは使いやすさ、SEO、リンク/コンテンツの共有に関連する非常に具体的なニーズを満たすように設計されています。

Html.ActionLinkを使用して、現在のルートデータにフォールバックせずに(または、可能であれば、ルートセグメントを明示的に除外する必要がある)、それらのリンクが同じアクションメソッドにつながる場合でも、ページへのリンクを生成するにはどうすればよいですか?

ルートセグメントを明示的に除外する必要がある場合、メソッドがルートをクエリ文字列パラメーターとしてレンダリングしないようにするにはどうすればよいですか?

この一見小さな問題が私たちに驚くほどの悲しみを引き起こしており、私はそれを解決するための助けに感謝します。

編集:LukLedの要求に応じて、ActionLink呼び出しのサンプルを次に示します。

// I've made it generic, but this should call the Search action of the 
// ItemController, the text and title attribute should say "Link Text" but there
// should be no parameters - or maybe just the defaults, depending on the route.
// 
// Assume that this can be called from *any* page but should not be influenced by
// the current route - some routes will be called from other sections with the same
// structure/parameters.
Html.ActionLink( 
    "Link Text",
    "Search", 
    "Item", 
    new { }, 
    new { title = "Link Text" } 
);
4

3 に答える 3

21

Html.ActionLinkまたは(または任意のURL生成メソッド)を呼び出すときにルート値をnullまたは空の文字列に設定するとHtml.RouteLink、「アンビエント」ルート値がクリアされます。

たとえば、標準のMVCコントローラー/アクション/ IDルートでは、「ホーム/インデックス/123」を使用しているとします。呼び出すとHtml.RouteLink(new { id = 456 })、MVCはとの「アンビエント」ルート値に気付くでしょcontroller="Home"action="Index"。また、の周囲ルート値にも気付くid="123"でしょうが、それは明示的な「456」によって上書きされます。これにより、生成されたURLは「Home / Index/456」になります。

パラメータの順序も重要です。たとえば、と呼んだとしますHtml.RouteLink(new { action = "About" })。「About」アクションは現在の「Index」アクションを上書きし、「id」パラメーターは完全にクリアされます!しかし、なぜ、あなたは尋ねますか?パラメータセグメントを無効にすると、それ以降のすべてのパラメータセグメントが無効になるためです。この場合、「action」は新しい明示的な値によって無効化されたため、その後に続く明示的な値を持たない「id」も無効化されます。したがって、生成されるURLは「Home / About」(IDなし)になります。

この同じシナリオで呼び出した場合Html.RouteLink(new { action = "" })、空の文字列で「アクション」を無効にしたため、生成されたURLは「ホーム」になります。その後、無効化された「アクション」の後にあるため、「id」も無効になります。 "。

于 2009-12-01T18:33:36.807 に答える
4

問題の根本にある解決策

最適な解決策(回避策のような匂いはしません)は、ルートがあり、ルーティングにある問題を解決するもののようです。

URLを生成するときに除外/削除する必要があるルート値の名前を定義できるというカスタムRouteクラスを作成しました。RouteWithExclusions問題は、ルーティングがルートテーブルを通過し、後続のルートが同じルート値名を持たない場合です...

問題全体は私のブログ投稿で詳細に説明されており、すべてのコードもそこに提供されています。それをチェックしてください、それはあなたがこのルーティング問題を解決するのを助けるかもしれません。また、追加のパラメーターを受け取る2つの追加MapRouteの拡張メソッドを作成しました。

于 2011-03-17T14:29:17.393 に答える
1

リンクを完全に制御したい場合は、自分でリンクを作成してください。

<a href="~/variableA/variableB/<%= Html.Encode(Model.Target) %>">Click Here</a>

href属性内で必要なものを置き換えます。

于 2009-11-30T02:34:14.933 に答える