31

ショッピング カートに商品を表示するアクション メソッドがあるとします。

 // ProductsController.cs
 public ActionMethod Index(string gender) {

      // get all products for the gender
 }

Url.RouteUrl他の場所では、サイト上の他のページへの HREF リンクを作成するために使用しているすべてのページに表示されるマストヘッドで:

 <a href="<%= Url.RouteUrl("testimonials-route", new { }) %>" All Testimonials </a>

これは、以下の最初のルートtestimonials-routeで定義されています。global.ascx上記の への呼び出しでRouteUrlは が提供されませんgenderが、ルートはデフォルトの「中立」で定義されているため、Testimonials.Index("neutral") が呼び出されることが予想されます。

 routes.MapRoute(
  "testimonials-route",
  "testimonials/{gender}",
  new { controller = "Testimonials", action = "Index", gender = "neutral" },
  new { gender = "(men|women|neutral)" }
 );

routes.MapRoute(
  "products-route",
  "products/{gender}",
  new { controller = "Products", action = "Index", gender = (string)null },
  new { gender = "(men|women|neutral)" }
 );

誰かがページにアクセスすると、HREF/products/womenを取得します。/testimonials/women 誰かがページ/productsにアクセスすると、空の HREF を取得します (RouteUrl の呼び出しは null を返します)。

でもそれって意味ないですよね?ルート値を提供しない場合、testimonials-routeデフォルトであるはずですか?'neutral'

何が起こっているかというと、Url.RouteUrl(routeName, routeValues)ヘルパー拡張機能は最初にrouteValuesパラメーターでgenderルート値を探し、その辞書で見つからない場合は現在の URL を調べます (Url は UrlHelper オブジェクトであることを思い出してください)。利用可能な現在のリクエストのコンテキストを持っています)。

これは、男性用の製品ページにいる場合、男性用の証言へのリンクを提供するというおそらく良い効果がありますが、RouteUrl呼び出しで値を渡さず、明示的に「ニュートラル」をglobal.asax.csファイルのデフォルト。

訪問した場合、ルート/products/をトリガーし、メソッドが呼び出されました。の呼び出しは、 を使用して URL を作成するときに、実際に THIS null 値を継承します。inのデフォルトを' に指定しましたが、依然としてこの null 値を使用しているため、ルートが失敗し、null が返されます。[注: (men|women|neutral) に制約があり、null がそれに適合しないため、ルートは失敗します]'products-route'Products(null)Url.RouteUrl()gendertestimonials-routegender'testimionials-routeRouteUrl

実際にはもっと恐ろしいことになります - 「コントローラ」と「アクション」が同じ方法で継承できるという点で。これにより、デフォルトのコントローラーを持つ明示的なルート名で RouteUrl(...) を呼び出した場合でも、URL が完全に間違ったコントローラーに生成される可能性があります。

この場合、問題がわかれば、さまざまな方法で非常に簡単に修正できますが、別のケースでは危険な動作を引き起こす可能性があります。これは仕様によるものかもしれませんが、間違いなく怖いです。

4

2 に答える 2

26

私の解決策はこれでした:

HtmlExtension ヘルパー メソッド:

    public static string RouteUrl(this UrlHelper urlHelper, string routeName, object routeValues, bool inheritRouteParams)
    {
        if (inheritRouteParams)
        {
            // call standard method
            return urlHelper.RouteUrl(routeName, routeValues);
        }
        else
        {
            // replace urlhelper with a new one that has no inherited route data
            urlHelper = new UrlHelper(new RequestContext(urlHelper.RequestContext.HttpContext, new RouteData()));
            return urlHelper.RouteUrl(routeName, routeValues);
        }
    }

私は今できる:

Url.RouteUrl('testimonials-route', new { }, false)

コンテキストに関係なく、常に同じように動作することを確認してください。

それが機能する方法は、既存のものを取得してUrlHelper、空白の「RouteData」で新しいものを作成することです。これは、継承するものがないことを意味します (null 値であっても)。

于 2009-07-18T20:03:24.120 に答える
2

ここで何かが足りないかもしれませんが、次のように設定してみませんか:

グローバル asax で、2 つのルートを作成します。

routes.MapRoute(
    "testimonial-mf",
    "Testimonials/{gender}",
    new { controller = "Testimonials", action = "Index" }
);

routes.MapRoute(
    "testimonial-neutral",
    "Testimonials/Neutral",
    new { controller = "Testimonials", action = "Index", gender="Neutral" }
);

次に、Url.RouteUrl の代わりに Url.Action を使用します。

<%= Url.Action("Testimonials", "Index") %>
<%= Url.Action("Testimonials", "Index", new { gender = "Male" }) %>
<%= Url.Action("Testimonials", "Index", new { gender = "Female" }) %>

私のマシンでは、次の URL に解決されます。

/Testimonials/Neutral 
/Testimonials/Male 
/Testimonials/Female

これが許容できる解決策かどうかはわかりませんが、代替手段ですよね?

于 2011-01-08T01:55:49.590 に答える