2011-12-20 15 views
6

検索結果ページ全体にフォームポスト(ビューモデル)の結果を保持する最善の方法はありますか?ASP.NET MVC RouteValueDictionaryとComplexオブジェクト

私はチェックボックスを含む検索フォームを持っています。この形式は、このビューモデルをポストバック私は(EFを使用して)、クエリを構築するために値を使用して取得すると

public class SearchViewModel 
{ 
    public string Name { get; set; } 
    public string[] Colors { get; set; } 
} 

のようなビューモデルを使用して構築されます。結果はPagedListに変換されます。

public class SearchController : Controller 
    { 
    public ActionResult Index() 
    { 
     //this displays the search form. 
     return View(); 
    } 

    public ActionResult Results(string game, SearchViewModel vm) 
    { 
     //this displays the results 
     ViewBag.SearchViewModel = vm; 
     var matches = _repository.AsQueryable() 
      .ColorOr(vm.Colors) 
      .WhereIf(vm.Name.IsNotEmpty(), x => x.Name.Contains(vm.Name.Trim())); 

      return View(matches.ToPagedList(1, 10)); 
    } 
} 

結果が表示されたら、Html.PagedListPagerとRouteValueDictionaryを使用してページングを作成します。

@Html.PagedListPager((IPagedList)Model, page => Url.Action("Results", new RouteValueDictionary(ViewBag.SearchViewModel))) 

ただし、作成されるURLは次のようになります。

http://localhost:5139/search?Name=test&Colors=System.String[]&PageIndex=0 

色の値は、値ではなくタイプになります。私は、URLがより多くのようになります期待していた。

http://localhost:5139/search?Name=test&Colors=[Blue,Pink,Yellow]&PageIndex=0 
  1. 検索結果ページ間でフォームポスト(ビューモデル)の結果を保持するための最良の方法は何ですか?
  2. RouteValueDictionaryは複雑なオブジェクトをサポートできますか?
  3. 何かを使用する必要がありますunbinder
  4. ViewDataまたはセッションを使用する方がよいでしょうか?
+0

:のようにリンクになり

using Unbound; Unbinder u = new Unbinder(); @Url.Action("Index", new RouteValueDictionary(u.Unbind(SearchParams))) 

。これは私の正確な質問です。 +1 –

答えて

2

私はシンプル見つけるこのような場合、のために行われ、かつ強力なてきたもの、結果のJSON文字列と、その後NewtonSoft JSON.netのようなものを使用して、(あなたのケースSearchViewModelに)JSONに私のビューモデルオブジェクトをシリアライズされ、 Zlib.DeflateStreamクラスを使用して文字列を単純に圧縮します(AES Rijndaelのようなものを使用することもできますが、遅くなることはまず無く、スピードを最優先にします)。

次に、もう一度使用する準備が整ったら(実質的にビューステートです)、JSON文字列を圧縮解除し、JSONからそれぞれの.NETオブジェクト(場合によってはSearchViewModel)にデシリアライズします。

私のために治療をしました。あなたは、管理できないURLや、シリアル化されているフォームフィールドのほんの一握りしか見ていない実際の測定可能なパフォーマンスの影響で終わることはありません。

まもなくコードサンプルで詳しく説明します。

更新:コードサンプル...

これは私があなたの特定のシナリオにどうなるのかです:ビューで

public ActionResult Results(string encryptedUrlViewModel, string game, SearchViewModel vm) 
{ 
    SearchViewModel searchUrlViewModel = null; 
    if (!string.IsNullOrEmpty(searchUrl)) { 
     // only first submission, no url view model set yet, so compress it and store.. 
     encryptedUrlViewModel = Convert.ToBase64String(
     DeflateStream.CompressString(JsonConvert.SerializeObject(vm))); 
     ViewBag.EncryptedUrlViewModel = encryptedUrlViewModel; 
    } 
    else { 
     var jsonUrlViewModel = DeflateStream.UncompressString(Convert.FromBase64String(encryptedUrlViewModel)); 
     searchUrlViewModel = JsonConvert.DeserializeObject(jsonUrlViewModel, typeof(SearchViewModel)) as SearchViewModel; 
     // at this point you should have a serialized 'SearchViewModel' object 
     // ready to use which you can then tweak your query below with. 
    } 
    var matches = _repository.AsQueryable() 
     .ColorOr(vm.Colors) 
     .WhereIf(vm.Name.IsNotEmpty(), x => x.Name.Contains(vm.Name.Trim())); 

    return View(matches.ToPagedList(1, 10)); 
} 

Results(string, SearchViewModel)アクションで

@Html.PagedListPager((IPagedList)Model, page => Url.Action("Results", new { encryptedUrlViewModel = ViewBag.EncryptedUrlViewModel })) 

コードは、いくつかの微調整が必​​要な場合があり、テストされていませんあなたのシナリオでは、それは、運の最高のようなものになります:)

あなたがページングの向こう側のURLでユーザーの要求を運びたい場合は、最初にPOSTリクエストではなく、GETリクエストとしてフォームが作成されなかった理由が考えられます。あなたが特に望んでいた理由POST?私はGETはあなたのColors配列を正しく運ぶでしょうが、あなたのビューモデルが正しく設定されていることを確認してください。 See this Haacked article for model binding to lists

+0

クリアするだけです。上で述べたように、最も単純な解決策は、フォームメソッドをPOSTからGETに変更することでした。 – detroitpro

+1

ハッハッハ....ドゥー。ああ私の手は無駄なコード化された解決策を作りました。まあ:)ある日のようなものが必要かもしれません。=) – GONeale

+0

少し遅れて来ますが、同様の問題に直面しています。正しいモデルバインディングを得るためには、検索フォーム全体+結果リストをHTMLフォームにラップしますか?ビュー全体がフォーム内にある場合、またはコントローラアクションとは別の引数である場合、検索ビューのページ分割部分はモデルですか? –

1

私は同じ問題を抱えていましたが、検索パラメータがありました。検索エンジンが使用していた色の名前のリストである色パラメータがありました。だから、あなたは黒と青に目を向けることができ、結果には黒と青の製品が含まれていました。

私はUnboundを使用しました。うわー

/MyRoute?color[0]=black&color[1]=blue 
関連する問題