2016-10-08 2 views
0

Je remplis une liste dans le viewmodel de la base de données, puis j'utilise cette liste pour remplir une liste déroulante dans la vue. Si je soumets le formulaire, le modèle est passé au serveur et si le modèle n'est pas valide, le modèle est renvoyé à la page. Maintenant, il ne semble pas y avoir un moyen d'envoyer la liste ou de la conserver de quelque façon que ce soit, donc je récupère la liste à partir de la base de données, ce qui la renvoie à la vue et peut être re -bound à la liste déroulante.Une meilleure façon de préserver les listes statiques entre les publications dans MVC?

Il me semble étrange que je doive interroger la base de données chaque fois pour voir les mêmes données statiques. Je peux mettre en cache la requête, mais n'y a-t-il pas une meilleure façon de le faire?

+0

Le repopulation de 'SelectList' dans la méthode POST est exactement ce que vous devriez faire. –

Répondre

1

Il existe plusieurs façons d'appréhender ce scénario commun. Voici quelques approches:

  1. Au lieu d'utiliser une pleine page post-retour, utilisez javascript pour « de manière asynchrone » soumettre le formulaire au contrôleur, et gérer la réponse . Cela devrait être la méthode préférée. Voir beaucoup de exemples: https://stackoverflow.com/search?q=mvc+ajax+post.
  2. Statique IEnumerable<SelectListItem> propriété/champ dans votre modèle de vue qui est rempli/ré-rempli le cas échéant. C'est l'approche la plus rapide et la plus sale.
  3. Créez une propriété "sérialisée" de votre propriété IEnumerable<SelectListItem> dans le modèle de vue et masquez-la dans le formulaire. Les getters et setters de ces propriétés sérialiseront et désérialiseront les IEnumerable<SelectListItem>. Si vous êtes complètement IMPUTATION AJAX et statics dans votre serveur, cette technique fonctionnera:

Par exemple, (cet exemple utilise Newtonsoft.JSONget it here)

Voir modèle

class MyViewModel 
{ 

    public string MyItemFromSelection { get;set;} 

    public IEnumerable<SelectListItem> MySelectList 
    { 
     get 
     { 
      return mySelectList; 
     } 
     set 
     { 
      mySelectList = value; 
      // serialize to a json string 
      SelectListSerialized = Newtonsoft.Json.JsonConvert.SerializeObject(value); 
     } 
    } 
    IEnumerable<SelectListItem> mySelectList; 

    public string SelectListSerialized 
    { 
     get 
     { 
      return selectListSerialized; 
     } 
     set 
     { 
      selectListSerialized = value; 
      if(MySelectList == null) 
      { 
       // if the MySelectList haven't been set, deserialize the string to populate MySelectList 
       MySelectList = Newtonsoft.Json.JsonConvert.DeserializeObject<IEnumerable<SelectListItem>>(value); 
      } 
     } 
    } 
    string selectListSerialized; 
} 

rasoir

@model MyViewModel 
<form> 
    @Html.HiddenFor(m => m.SelectListSerialized) 
    @Html.DropDownListFor(m => m.MyItemFromSelection, Model.MySelectList) 
</form> 
0

Je dirais qu'il est inefficace pour la liste d'être publié sur le serveur lorsque le serveur se soucie vraiment de la valeur sélectionnée.

Si vous souhaitez envoyer la même liste au même utilisateur à chaque fois, vous pouvez demander au client de mettre en cache la liste en utilisant quelque chose comme le stockage local.

Bien sûr, cela signifie que chaque utilisateur doit toujours obtenir la liste la première fois, donc sur le serveur, vous devrez toujours créer la liste. Si c'est quelque chose qui ne change pas souvent, j'utiliserais votre approche de mise en cache de la liste pour empêcher une attaque de base de données.

1

Vous pouvez simplement utiliser TempData si vous souhaitez conserver les données entre 2 demandes.

Récupère les données de la base de données et les stocke dans TempData. Lorsque vous effectuez le second appel au contrôleur, utilisez les données de la même tempdata.

Aucun appel db supplémentaire ne sera nécessaire pour le moment.

En outre, si vous souhaitez conserver et stocker cette valeur de tempdata dans la prochaine requête, vous pouvez simplement utiliser la fonction "keep" de tempdata pour cela.