上記の受け入れられた回答で解決策を試しました: Canonicalize パターン URL 戦略を使用し、カスタム IHttpHandler を返すカスタム IRouteHandler も追加します。それはほとんどうまくいきました。ここに私が見つけた1つの警告があります:
典型的な{controller}/{action}/{id}
デフォルト ルート、 という名前のコントローラーCatalogController
、およびその内部のアクション メソッドを次のように使用します。
ActionResult QuickSelect(string id){ /*do some things, access the 'id' parameter*/ }
「/catalog/quick-select/1234」へのリクエストは完全に機能することに気付きましたが、/catalog/quick-select?id=1234 へのリクエストは 500'ing でしたcontroller.Execute()
。id
アクション メソッド内では null です。
正確な理由はわかりませんが、MVC がモデル バインド中に値のクエリ文字列を見ていないかのように動作していました。したがって、受け入れられた回答の実装に関する何かがProcessRequest
、通常のモデル バインディング プロセス、または少なくともクエリ文字列値プロバイダーを台無しにしていたのです。
これは取り決めを破るものなので、デフォルトの MVC IHttpHandler を調べてみました (オープン ソースです!): http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/MvcHandler.cs
私はそれを完全に理解したふりをするつもりはありませんが、明らかにProcessRequest
、受け入れられた回答で起こっていることよりも、その実装において多くのことを行っています。
では、MVC がコントローラー/アクションを見つけられるように、着信ルート データからダッシュを削除するだけでよいのであれば、悪臭を放つ IHttpHandler 全体を実装する必要があるのはなぜでしょうか? ありません!GetHttpHandler
のメソッドでダッシュを切り取ってすぐに使用できるようにDashedRouteHandler
渡すだけで、252 行の魔法を実行できます。ルート ハンドラーは、2 番目のレートの IHttpHandler を返す必要はありません。requestContext
MvcHandler
tl:dr; - これが私がしたことです:
public class DashedRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.RouteData.Values["action"] = requestContext.RouteData.GetRequiredString("action").Replace("-", "");
requestContext.RouteData.Values["controller"] = requestContext.RouteData.GetRequiredString("controller").Replace("-", "");
return new MvcHandler(requestContext);
}
}