5

以前の質問 (送信 URL の生成中に予期しないルートが選択されました) の 1 つを続けるには、次のルートを検討してください (デフォルトなし、制約なし):

"{controller}/{month}-{year}/{action}/{user}"

このルートに一致する着信 URL を介していくつかのページをレンダリングしている間 (したがって、リクエスト コンテキストには各ルート セグメントの値が含まれます)、他のすべてのセグメントの正確な値を保持しながらmonthとのみを変更する URL を生成する必要があるとします。year

ルールに従って、リンクされた質問で言及しました (つまり、ルーティング システムは、指定されたパラメーターよりも URL パターンで以前に発生するセグメント変数に対してのみ値を再利用します。 )、匿名オブジェクトを介してのみ新しいを指定したmonth場合yearuserセグメントの値が失われます (つまり、ルートが一致しなくなります)。

私はこれを克服するための2つの方法を知っています:

  1. 匿名オブジェクトを指定しないでください。ただし、必要なセグメント値を右に設定し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;
            }
        }
    }
    
  2. 匿名オブジェクトの代わりに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

4

1 に答える 1

2
public static MvcHtmlString GetDateUrl(this RequestContext context, DateTime date)
{
    var values = context.RouteData.values;

    var data = new{
        controller = values["controller"]  ?? "Home";
        action = values["action"]  ?? "Index";
        month = date.Month;
        year = date.Year;
        user = context.HttpContext.User.Identity.Name;
    };

    string url = UrlHelper.RouteUrl(data);
    return MvcHtmlString.Create(url);
}

なぜそれをさらに複雑にするのですか?HttpContext で null チェックを行いたいと主張することもできますが、HttpContext のない RequestContext がある日は、ここでの null チェックはほとんど問題になりません。それか、プログラマーが非常にファンキーなことをしていて、アプリケーションがその栄光をすべて吹き飛ばして、動作しないことをしていることを知らせて、それが動作する前にそこで停止する必要があることを望んでいます。製造。

ここで他のことを追加でチェックしたくなるかもしれませんが、実際には、このメソッドの責任はここで終わります。日付を受け取り、ルート URL を MvcHtmlString として返すことになっています。限目。

パフォーマンスの観点から、URL を生成するときにここで特定のルート名を明示的に定義できますが、それを意味のあるものにするには、かなり大きなルート コレクションが必要です。このメソッドとルート構成の間に隠れた依存関係を作成することを考慮してください。誰かがルート名を変更した日、アプリが爆発し、理由を見つけるのが難しくなります。

RouteValueDictionary を使用することもできますが、理由はありません。私の記憶が正しければ、UrlHelper はとにかくオブジェクトを内部的に使用します。私が間違って覚えていたとしても、それを変換する能力は十分にあります。

参考文献: 「正確な場所と時間に必要なすべての値を指定してください」、Sanderson S.、Freeman A. - Pro ASP.NET MVC 3 フレームワーク

http://msdn.microsoft.com/en-us/library/dd505226(v=vs.108).aspx

于 2013-01-13T00:44:25.227 に答える