web-dev-qa-db-ja.com

MVC 3フォームポストおよび永続化モデルデータ

MVCフォームがどのように機能するかについてのいくつかの基礎が欠けていると思います。ホームページに検索フォームがあり、ユーザーが検索できる5つまたは6つの異なるフィールドがあります。そのため、この結果へのPOSTのアクションは問題ありません。結果アクションは次のようになります。

[HttpPost]
public ActionResult Results(SearchModel model)
{
    ResultsModel results = new ResultsModel();
    results.ResultList = SearchManager.Search(model).ToList();

    return View("Results", results);
}

この投稿では上記の方法を簡略化しましたが、考え方は同じです。したがって、これはすべて正常に動作します。結果ページに結果のリストが表示され、ユーザーは次のURLにあります。

http://www.site.com/results

だから...今、私はかなり一般的な何かをしたい。結果ページに2つのドロップダウンリストがあります。 「並べ替え」および「ページごとの結果数」。新しいパラメーターでクエリできるように、どうすればモデルデータの完全なセットをコントローラーに送り返すことができますか?実際には、SearchModelクラスには約60の異なるフィールドがあります。そのデータのすべてがモデルに含まれている可能性があります。 「ポストバック」ページにどのようにそれを永続化しますか?

この同じ質問には、ページングの方法についても少し困惑しています。私のページングリンクは次のようなURLに移動します。

http://www.site.com/results/2

しかし、それはGETリクエストに応答している(クエリ文字列に60フィールドのデータが必要ない)ことと、モデルデータがGETリクエスト間で渡されることを前提としていますが、そうではありません。

前にも言ったように、MVC 3、モデル、フォームポストでの作業に関する基礎が欠けていると思います。

誰かが私をここで正しい方向に向けるのを助けることができますか?物事を明確にするために、必要に応じてこの投稿を編集/更新させていただきます。

[〜#〜] edit [〜#〜]:私も指摘したいのですが、セッションにビューモデルを保存しないようにしたいです変数。このサイトは最終的にWebファームで負荷分散されることになります。可能な限りSessionの使用を避けようとしています。ただし、それが唯一の選択肢である場合は、別のセッション状態プロバイダーを構成しますが、そうしないことを望みます。

28
Scott

現在のSearchModelパラメーターをフォームのルート値に追加できます。 BeginFormのいくつかのバージョンでは、object/RouteValuesDictionaryを渡すことができます。

@Html.BeginForm("Action", "Controller", new { SearchModel = Model }, FormMethod.Post)

これにより、現在のSearchModel値がパススルーされるため、それらを再利用して次のページを取得できます。 SearchModelと同様に、現在のページのフォーム値を受け入れるコントローラーアクションを定義する必要があります。

私はフォーム投稿でこれを行っていませんが、私がやったことから、そしてドキュメントが言うことから、これは私が始めるところです。もちろん、これは、ページ上の各ページ番号「リンク」が投稿を行う必要があることも意味します。ユーザーがブラウザーの「戻る」ボタンを使用できるようにしたい場合、これはユーザーにとって本当に不便です。

このコンテキストでは、ページ番号をURLの一部として表示できるようにするルートを定義することができます-"Action/Controller/{page}"。しかし、フォームが投稿を行っていることを考えると、それがどのように機能するのかわかりません。

コメントへの応答:

ええ、ルート値を使用してSearchModelを各ページリンクに追加できますが、上記のコメントで述べたように、リンクは「取得」を行うため、ユーザーにはSearchModelがリンクの一部としてシリアル化されます。

どちらにしても、ルート値を使用すると、非表示フィールド、セッション、またはTempDataを使用せずに元のSearchModelを取得することができます。

17
BJ Safdie

SearchModelクラスには、検索条件と結果を含める必要があります。以下のようなもの。結果にPagedListを使用すると、現在のページ、合計ページ、合計アイテムなどが含まれます。値を含む検索条件を記述するだけで、ページ内の情報量を制限できます。

public class SearchModel
{
    public string Product { get; set; }
    public string Sku { get; set; }
    public string Size { get; set; }
    public string Manufacturer { get; set; }
    // etc...

    public PagedList ResultsList { get; set; }
}


[HttpPost]
public ActionResult Results(SearchModel model)
{
    model.ResultList = SearchManager.Search(model).ToList();
    return View(model);
}
8
37Stars

ここで思いつくオプションの1つは、カスタムセッションプロバイダー(MemcachedまたはWindows Server AppFabric)として機能することをサポートする分散キャッシュシステムを実装することです。これにより、負荷分散環境でTempData(およびSession)を使用できますそのようです:

[HttpPost]
public ActionResult Results(SearchModel model)
{
    ResultsModel results = new ResultsModel();
    results.ResultList = SearchManager.Search(model).ToList();

    TempData["SearchModel"] = model;

    return View("Results", results);
}

    [HttpGet]
    public ActionResult Results(int? page)
    {
        SearchModel model = (SearchModel)TempData["SearchModel"];

        ResultsModel results = new ResultsModel();
        results.ResultList = SearchManager.Search(model).ToList();

        TempData["SearchModel"] = model;

        return View("Results", results);
    }

このアプローチに関する考えはありますか?リクエスト間で渡される検索パラメータを取得するためだけに通過する必要があるように思えます。それとも、WebFormsの舞台裏で起こっているこのすべてに甘やかされただけかもしれません。 :)

2
Scott

これは、Webformsのだまされた男にとって別の興味深いオプションのようです;) HTMLHelperのシリアル化を使用したASP.NET MVCでのモデル状態の保持 何らかの種類のViewStateインカネーション。 MVC Futuresの一部です。 Futuresプロジェクトにどれくらいの時間がかかるか、なぜメインライブラリに入らないのかはわかりません。

0
Boris Bucha