3

私の ASP.NET MVC 4 アプリケーションでは、複数のタグでフィルター処理できます。HTML では、次のようになります。

<form>
  <label>
    <input type="checkbox" name="tag" value="1">One
  </label>
  <label>
    <input type="checkbox" name="tag" value="2">Two
  </label>
  <label>
    <input type="checkbox" name="tag" value="3">Three
  </label>
  <input type="submit" name="action" value="Filter">
</form>

1 番目と 3 番目のチェックボックスをオンにすると、クエリ文字列が次のようにシリアル化され?tag=1&tag=3、コントローラーは次のクラスの型を持つオブジェクトを適切に渡します。

// Filter class
public class Filter { 
    public ICollection<int> tag { get; set; }
}

// Controller method
public ActionResult Index(AdFilter filter)
{
    string url = Url.Action("DoFilter", filter);
    // url gets this value:
    // "/controller/Index?tag=System.Collections.Generic.List%601%5BSystem.Int32%5D"
    // I would expect this:
    // "/controller/Index?tag=1&tag=3"
    ...
 }

ただし、 を呼び出すとUrl.Action、実際の値ではなく、コレクションの型名がシリアル化されます。

これはどのように行うことができますか?


MVC の標準インフラストラクチャは、入力として記述された複数のキーを処理できます。逆にそれを処理できる標準インフラストラクチャはありませんか? 何か不足していますか?

4

4 に答える 4

4

次の方法でそれを行うことができます。

string url = Url.Action("DoFilter", TypeHelper2.ObjectToDictionary(filter) );

これTypeHelper2.ObjectToDictionaryは、.NET の内部メソッドの修正版であり、この2 つのファイルの要点にあります。

動作の変更: アイテムが を実装すると、アイテムIEnumerableごとに、キーとして返される辞書にエントリが作成されます"Name[index]"(インデックスは 0 ベースです)。これが可能なのは、MVC コントローラーのバインダーがtag=1&tag=3tag[0]=1&tag[1]=3クエリ文字列の両方を処理できるためです。

于 2015-02-12T16:31:15.143 に答える
3

簡単だがそれほどエレガントではない解決策は次のとおりです。

  public ActionResult Index(AdFilter filter)
  {
     string parameters = "?";
     foreach (var item in filter.tag)
        {
            parameters += string.Format("tag={0}&", item);
        }
     //trimming the last "&"
     parameters = parameters.TrimEnd(parameters[parameters.Length - 1]);
     string url = Url.Action("DoFilter") + parameters;

  }
于 2015-02-12T16:44:51.930 に答える
2

上記の2つの回答に賛成票を投じました-どちらも完全に良い回答です。この側面 (アクションへのリダイレクトまたはリダイレクト先の URL の生成) では、MVC は配列をまったく「好き」ではありません。

私が見ることができる2つのさらなるアプローチがあります:

1)TempDataを使用して配列を取得して永続化します(たとえば、この記事の下部にあります)

2) AdFilter のカスタム モデル バインダーを作成して使用する

私は後者を選びます-テスト可能でより決定論的です(また、サーバーファームのシナリオに入ったときにTempDataがどのように機能するかわかりません)

考慮したいもう 1 つのことは、Index アクションからの戻りとしてのようなものを使用することです。

return View("DoFilter", new AdFilter(){tag = tag});

(これにより、ブラウザーで "index?tag[0]=1&tag 1 =2" urlを維持しながら、Dofilter ビューが返されます)

最後に、フィルター条件をブラウザーに送り返すためだけにフィルター条件を取得しているように感じます。これにより、ブラウザーはフィルター結果を再度要求できます。おそらく、フォームのアクションを最初から「DoFilter」に投稿するように設定することをお勧めします。

<form  method="post" action="DoFilter"> 

HTH

于 2015-02-17T13:13:36.627 に答える
1

Url.Action()オブジェクトを受け入れるオーバーロードを使用して、ルート パラメーターを生成します。内部的には、これはリフレクションを使用して各プロパティ名とその.ToString()値の辞書を作成することで機能します。

単純な値型の場合、これはName = "doekman"( になる/DoFilter?Name=doekman) かもしれませんが、複雑なオブジェクトまたはコレクションであるプロパティの場合は、型名 (つまり、.ToString()値) を返します。再帰は行われず、クエリ文字列には長さの制限があるため、再帰が複雑なオブジェクトやコレクションに対して行われた場合、コレクションに多くのアイテムが含まれているとすぐに制限を超えて例外をスローするため、これは理にかなっています (そして、実際に醜いクエリ文字列)。

したがって、手動で生成しない限り(またはクエリ文字列を生成する独自のヘルパーを作成しHow can this be done?ない限り)、あなたはできませんRouteValueDictionary

于 2015-02-18T11:19:50.770 に答える