web-dev-qa-db-fra.com

MVC 3 form post et persistant modèle de données

Je pense que je manque certains fondamentaux sur le fonctionnement des formulaires MVC. J'ai un formulaire de recherche sur ma page d'accueil qui contient cinq ou six champs différents sur lesquels un utilisateur peut rechercher. J'ai donc ce message à mes actions de résultats très bien. L'action Résultat ressemble à ceci:

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

    return View("Results", results);
}

J'ai simplifié la méthode ci-dessus pour ce post, mais l'idée est la même. Donc tout cela fonctionne bien. Ma page de résultats s'affiche avec la liste des résultats et mon utilisateur est à l'URL suivante:

http://www.site.com/results

Alors ... maintenant je veux faire quelque chose d'assez commun. J'ai deux listes déroulantes sur la page de résultats. "Trier par" et "# de résultats par page". Comment puis-je le faire et renvoyer l'ensemble complet des données du modèle au contrôleur afin que je puisse interroger avec les nouveaux paramètres? En réalité, la classe SearchModel a environ 60 champs différents. Potentiellement, toutes ces données pourraient être contenues dans le modèle. Comment persistez-vous sur une page "post back"?

Cette même question m'a un peu perplexe sur la façon de faire de la pagination aussi. Mes liens de pagination iraient vers une URL comme:

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

Mais cela suppose que nous répondons à une demande GET (je ne veux pas 60 champs de données dans la chaîne de requête) et que les données du modèle sont transmises entre les demandes GET, ce qui, je le sais, n'est pas le cas.

Comme je l'ai dit, je pense que je manque certains principes fondamentaux concernant le travail avec MVC 3, les modèles et les formulaires.

Quelqu'un peut-il m'aider à me diriger dans la bonne direction ici? Je serai heureux de modifier/mettre à jour ce message au besoin pour clarifier les choses.

[~ # ~] edit [~ # ~] : Je voulais aussi souligner, je voudrais éviter de stocker le modèle de vue dans une session variable. Ce site finira par être équilibré en charge dans une batterie de serveurs Web et j'essaie vraiment d'éviter d'utiliser Session si possible. Cependant, si c'est la seule alternative, je configurerai un autre fournisseur d'état de session, mais je préférerais ne pas le faire.

28
Scott

Vous pouvez ajouter vos paramètres SearchModel actuels aux valeurs de l'itinéraire pour votre formulaire. Plusieurs versions de BeginForm vous permettent de passer un objet/RouteValuesDictionary.

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

Cela devrait transmettre vos valeurs SearchModel actuelles afin que vous puissiez les réutiliser pour obtenir la page suivante. Vous devez définir une action de contrôleur qui acceptera toutes les valeurs de formulaire de la page actuelle ainsi que le SearchModel.

Je n'ai pas fait cela avec des messages de formulaire, mais d'après ce que j'ai fait et d'après ce que disent les docs, c'est par là que je commencerais. Bien sûr, cela signifie également que chacun de vos "liens" de numéro de page sur la page devra faire des publications. C'est vraiment gênant pour les utilisateurs s'ils veulent pouvoir utiliser le bouton Retour dans le navigateur.

Dans ce contexte, vous pouvez essayer de définir un itinéraire qui permet au numéro de page d'apparaître comme une partie de l'URL - "Action/Contrôleur/{page}". Cependant, je ne sais pas comment cela fonctionnera étant donné que le formulaire fait un post.

Réponse au commentaire:

Oui, vous pouvez utiliser des valeurs de route pour ajouter le SearchModel à chaque lien de page, mais comme je l'ai dit dans le commentaire ci-dessus, puisque les liens feront un "get", vos utilisateurs verront le SearchModel sérialisé comme une partie du lien.

Dans les deux cas, l'utilisation des valeurs de route est votre réponse pour récupérer votre SearchModel d'origine sans utiliser les champs masqués, Session ou TempData.

17
BJ Safdie

Votre classe SearchModel doit contenir vos critères de recherche et vos résultats. Quelque chose comme ci-dessous. Si vous utilisez une PagedList pour vos résultats, elle contiendra la page actuelle, le nombre total de pages, le nombre total d'éléments, etc. Vous pouvez limiter la quantité d'informations dans votre page en écrivant uniquement les critères de recherche qui contiennent des valeurs.

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

L'une des options que je propose ici consiste à implémenter un système de mise en cache distribué qui prend en charge le rôle de fournisseur de session personnalisé (par exemple Memcached ou Windows Server AppFabric), me permettant ainsi d'utiliser TempData (et Session) dans un environnement à charge équilibrée. ainsi:

[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);
    }

Des réflexions sur cette approche? Il semble que beaucoup de choses à passer juste pour que les paramètres de recherche soient passés entre les requêtes. Ou peut-être que j'étais juste gâté avec tout cela qui se passait en coulisses avec WebForms. :)

2
Scott

Cela semble être une autre option intéressante pour les gars gâtés Webforms;) État du modèle persistant dans ASP.NET MVC utilisant Serialize HTMLHelper Une sorte d'incarnation de ViewState. Il fait partie de MVC Futures. Je ne sais pas combien de temps il est dans le projet Futures et pourquoi il ne peut pas entrer dans la lib principale.

0
Boris Bucha