4

次のような URL を処理したいと思います。

/Id/Key1/Value1/Key2/Value2/Key3/Value3/

現在、次のようなルールを設定しています。

/{id}/{*parameters}

オブジェクトは、応答の形成に関与するすべてのアクションにparameters単一として渡されます。stringこれは機能しますが、いくつか問題があります。

  1. 各アクションはstring、それ自体を解決する必要があります。もちろん、私は を に変換する拡張メソッドを作成しましたがstringDictionary<string, string>ディスパッチ メカニズムがメソッドに をDictionary<string, string>直接渡すか、実際のペアを個別の引数として指定した方がよいでしょう。
  2. アクション リンクは、従来の形式 ( ) を使用してパラメータを追加します?Key1=Value1。目的の形式で特殊なヘルパーを作成できると思いますが、既存のオーバーロードを上記のルーティング規則に従うようにする方法があれば、それを好むでしょう。

上記を行う方法はありますか?

4

2 に答える 2

4

カスタムルートを書くことができます:

public class MyRoute : Route
{
    public MyRoute()
        : base(
            "{controller}/{action}/id/{*parameters}",
            new MvcRouteHandler()
        )
    {
    }

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var rd = base.GetRouteData(httpContext);
        if (rd == null)
        {
            return null;
        }

        string parameters = rd.GetRequiredString("parameters");
        IDictionary<string, string> parsedParameters = YourExtensionMethodThatYouAlreadyWrote(parameters);
        rd.Values["parameters"] = parsedParameters;
        return rd;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        object parameters;
        if (values.TryGetValue("parameters", out parameters))
        {
            var routeParameters = parameters as IDictionary<string, object>;
            if (routeParameters != null)
            {
                string result = string.Join(
                    "/", 
                    routeParameters.Select(x => string.Concat(x.Key, "/", x.Value))
                );
                values["parameters"] = result;
            }
        }
        return base.GetVirtualPath(requestContext, values);
    }
}

そのように登録できます:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.Add("my-route", new MyRoute());

    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

これで、コントローラーのアクションは次のパラメーターを取ることができます。

public ActionResult SomeAction(IDictionary<string, string> parameters)
{
    ...
}

このパターンに従ってリンクを生成することに関する限り、次のように簡単です。

@Html.RouteLink(
    "Go", 
    "my-route", 
    new {
        controller = "Foo",
        action = "Bar",
        parameters = new RouteValueDictionary(new { 
            key1 = "value1", 
            key2 = "value2",
        }) 
    }
)

またはあなたがしたい場合<form>

@using (Html.BeginRouteForm("my-route", new { controller = "Foo", action = "Bar", parameters = new RouteValueDictionary(new { key1 = "value1", key2 = "value2" }) }))
{
    ...    
}
于 2013-06-23T16:07:57.403 に答える
1

特殊なディクショナリ用に独自のモデル バインダーを記述します。ある場合、各アクション メソッドで文字列を解析する必要はありません。

于 2013-06-23T16:02:48.727 に答える