以前の質問 (送信 URL の生成中に予期しないルートが選択されました) の 1 つを続けるには、次のルートを検討してください (デフォルトなし、制約なし):
"{controller}/{month}-{year}/{action}/{user}"
このルートに一致する着信 URL を介していくつかのページをレンダリングしている間 (したがって、リクエスト コンテキストには各ルート セグメントの値が含まれます)、他のすべてのセグメントの正確な値を保持しながらmonth
とのみを変更する URL を生成する必要があるとします。year
ルールに従って、リンクされた質問で言及しました (つまり、ルーティング システムは、指定されたパラメーターよりも URL パターンで以前に発生するセグメント変数に対してのみ値を再利用します。 )、匿名オブジェクトを介してのみ新しいを指定したmonth
場合year
、user
セグメントの値が失われます (つまり、ルートが一致しなくなります)。
私はこれを克服するための2つの方法を知っています:
匿名オブジェクトを指定しないでください。ただし、必要なセグメント値を右に設定し
context.RouteData.Values
ます。目的の URL を生成した後、元の値を戻して、残りのページのレンダリングを元のリクエスト セグメント値で実行します。これは次のようになります。public static MvcHtmlString GetDateUrl(this RequestContext context, DateTime date) { UrlHelper url = new UrlHelper(context); object month = null, year = null; if (context.RouteData.Values.ContainsKey("month")) { month = context.RouteData.Values["month"]; year = context.RouteData.Values["year"]; } try { context.RouteData.Values["month"] = date.Month; context.RouteData.Values["year"] = date.Year; return MvcHtmlString.Create( url.Action((string)context.RouteData.Values["action"])); } finally { if (month == null) { if (context.RouteData.Values.ContainsKey("month")) { context.RouteData.Values.Remove("month"); context.RouteData.Values.Remove("year"); } } else { context.RouteData.Values["month"] = month; context.RouteData.Values["year"] = year; } } }
匿名オブジェクトの代わりに
RouteValueDictionary
、現在のリクエスト コンテキストに基づいて を使用します。public static MvcHtmlString GetDateUrl(this RequestContext context, DateTime date) { UrlHelper url = new UrlHelper(context); var values = new RouteValueDictionary(context.RouteData.Values); values["month"] = date.Month; values["year"] = date.Year; string action = (string)context.RouteData.Values["action"]; return MvcHtmlString.Create(url.Action(action, values)); }
2 番目のオプションはより簡潔に話されているように見えますが、最初のオプションは追加の辞書を作成せず、リクエスト コンテキストを操作します。
どちらの方法が良いですか?それとも、私は何か間違ったことをしている/理解しているのでしょうか?
Sanderson S.、Freeman A. - Pro ASP.NET MVC 3 フレームワーク (第 3 版)は、セグメント値の再利用に依存するのではなく、正確な場所と時間に必要なすべての値を指定すると述べています。
このタスクを実行するために見つけた方法を示しましたが、置換されたセグメントがルートの早い段階で発生した場合、セグメントの値を置き換えて他の値を保持する正しい (または単により良い) 方法は何ですか?
編集
Jani Hyytiäinen の回答に基づいています。ご紹介のルートは一例です。ターゲット mvc アプリケーションには異なるルートが含まれています。一部のルートは、これよりも複雑な場合があります。したがって、私が探しているアプローチは、それらのいずれでも機能するはずです。この拡張メソッドは知っているだけで、他のすべてのセグメントを保持しながら、month
変更する必要があると思います。他のセグメントの数は任意です。したがって、それらすべてをハードコーディングすることは、可能な解決策ではありません。さらに、リクエストコンテキスト自体を除いて、現在のセグメント値のソースがあります。year