2010-12-15 15 views
3

これは、一連のチェックボックスをモデルに正しくバインドする方法に関する質問ではありませんプロパティ(一般的な質問) - 私のサイトはPOSTやGET +クエリ文字列のリクエストからチェックボックスの値を完全に読み取って動作します。ASP.NET MVCで、Html.ActionLinkで繰り返し名前( '?v = 1&v = 2&v = 3')クエリ文字列を生成する方法

これは、Html.ActionLinkを使用して、複数のチェックボックス値をクエリ文字列で正しくフォーマットするリンクを生成する方法です。

だから私は、次のモデルがあります:

public class ModelType 
{ 
    public string[] V { get; set; } 
} 

をそして、私は3つの値(および、はい、と値の組み合わせを)持っているように私には、たとえば、ビューでそのモデルに3つのチェックボックスをバインドします。フォームはその後、生成されたクエリ文字列は、当然のことながら、?V=1&V=2&V=3でGETとしてサーバーに送信されたときにすべての3つの値がチェックされている場合はここ

は、最終的なHTML

<INPUT id="chk1" value="1" type="checkbox" name="V"> 
<INPUT id="chk2" value="2" type="checkbox" name="V"> 
<INPUT id="chk3" value="3" type="checkbox" name="V"> 

です。

モデルバインディングは美しく動作し、すべてが幸せです。

には、同じクエリ文字列を生成するために匿名型またはRouteValueDictionaryを渡して、同じアクションへのリンクをに生成したいとします。あなたはこのような何かをするだろう論理状態:

バージョン1:ビュー上のモデルとしてModelTypeのインスタンスの場合:

<%= Html.ActionLink("Test link", null /* action name */, new { V = Model.V }) %> 

バージョン2:配列として直接「V」メンバーを初期化:

<%= Html.ActionLink("Test link", null /* action name */, 
    new { V = new string[] { "1", "2", "3" } }) %> 

は、[両方のケースでこれらの匿名型の両方がリンク生成が発生する前に、このようなになって取得しているので、質問では、私はRouteValueDictionaryを言う。]

いずれの場合も、生成されるクエリ文字列は次のとおりです。?V=System.String%5B%5D

これは、リンクジェネレータが単に配列のToString()を呼び出すためです。 MVCに値?V=1&V=2&V=3を生成させる値を渡す方法はないようです。

どちらの言語は、私たちが行うことができますので、:

new { V="1", V="2", ... } 

NOR RouteValueDictionaryは、私たちが行うことができます:

d["V"] = "1"; d["V"] = "2"; ... 

は私もRouteValueDictionaryを前処理の必死の対策を試してみた、のためになるようにそれぞれIEnumerable<string>、私はコンマで区切られたそれぞれの値を持つ単一の文字列を生成し、その文字列を書き戻します - クエリ文字列はこのように終わります:?V=1%2C2%2C3

もちろん、MVCはそのような文字列を配列に自動的にバインドしません(配列内にコンマを含む文字列を1つだけ取得します)。だから、この方法で束縛されるそれぞれの財産は、私のために飛び抜ける少数のあふれているように見えます。

だから私は立ち往生しているようです。

何か不足していますか?私がしたいことをするActionLinkの特別なバージョンを書く必要がありますか?

いつものように、大変感謝しています。

答えて

3

私はこれを調べてこれを調べましたが、これは私の見解です。私は誰かがより楽観的な答えを出すことができると思うが、どういうわけか私はそうではないと思う。すべての方法を通じてHtml.ActionLink拡張メソッドに続いて

、それはと(咳咳!)内部クラスSystem.Web.Mvc.ParsedRouteを密封し、それがSystem.Web.Routing方法Bindです(咳)によって生成された生成コアURLアセンブリ。この方法の一番最後に

(これはリフレクターのリストである) - これは、クエリ文字列を生成する方法である:

if (unusedNewValues.Count > 0) 
{ 
    bool flag5 = true; 
    foreach (string str2 in unusedNewValues) 
    { 
     object obj5; 
     if (acceptedValues.TryGetValue(str2, out obj5)) 
     { 
      builder.Append(flag5 ? '?' : '&'); 
      flag5 = false; 
      builder.Append(Uri.EscapeDataString(str2)); 
      builder.Append('='); 
      builder.Append(Uri.EscapeDataString(
       Convert.ToString(obj5, CultureInfo.InvariantCulture))); 
     } 
    } 
} 

私はunusedNewValuesを意味しHashSet<string>であることを最初に言及する必要があります - 残念ながら - ことの名前と値はのペアでのみ表示されます。

a=b&a=c(...)文字列でデータ文字列を切り取ることはできません。文字列値がエスケープされているためです。したがって、ルーティングフレームワークを置き換えない限り、このようなクエリ文字列をMvcで生成することはできません。

その結果、代替のような何かをコレクション・データ型を書くことになります(これは汚い実装である)以下:

public class StringCollection : List<string> 
{ 
    public override string ToString() 
    { 
    //use the pipe character as a delimiter - but this doesn't work 
    //if the strings being carried around ccould naturally contain '|'! 
    return string.Join("|", this.ToArray()); 
    } 
} 

そしてDefaultModelBinderから派生したカスタムモデルバインダーを(実装)は、最初にデフォルトのメソッドを使用し、結果のコレクションに '|'を持つ文字列が1つしかないかどうかをチェックします。その中の文字。そうであれば、コレクションを後処理し、その内容を単一文字列の展開された値で置き換えます。

これは恐ろしいですが、私が現在考えることができるすべての解決策の中で最も厄介です。

はちょうど今、文字列値を照会するためにバインドされるかもしれない文字列のコレクションを使用するすべての私の既存のモデルタイプへの変更の負担をしなければならない...

1

は最近、同様の問題がありました。私はHtmlHelper/RouteValueDictionaryを破棄して、ちょうどゼロからURLを構築しました。何かが好き:

<a href="/Controller/Action?<%: string.Join("&", set.Select(i => "v=" + i))%>">Link</a> 

誰もが味わうことはできませんが、私のために働いています。

関連する問題