1

Je suis nouveau dans MVC. J'ai une vue qui contient beaucoup de listes déroulantes et viewmodel avec beaucoup de listes. La plupart de ces listes sont statiques, donc je veux mettre en cache les enregistrements récupérés. Je peux le faire avec (personnalisés) classeurs de modèles, mais je ne aime pas que pour utiliser réellement (personnalisé) Modèle Binder Je dois ajouter le paramètre pour chaque objet dans la méthode d'action comme ceci:Puis-je utiliser ModelBinder pour obtenir un objet sans ajouter de paramètre à l'action?

public ViewResult SubmitNewValue(MyViewModel viewMod, IEnumerable<List1> list1, IEnumerable<List2> list2, IEnumerable<List3> list3 ...) 
{ 
viewMod._list1 = list1; 
viewmod._list2 = list2; 
viewMod._list3 = list3; 
... 
return View(viewMod); 
} 

Ce que je pense regarderait mieux vaut quelque chose comme:

public ViewResult SubmitNewValue(MyViewModel viewMod) 
{ 
viewMod._list1 = ModelBinders.GetInstanceFor<List1>(); 
viewmod._list2 = ModelBinders.GetInstanceFor<List2>(); 
viewMod._list3 = ModelBinders.GetInstanceFor<List3>(); 
//I am able to wrap above to separate function like PrepareViewModel(viewMod) 
... 
return View(viewMod); 
} 

Y at-il une fonction/façon de faire cela?

Je ne suis pas sûr si j'ai choisi la bonne approche mais mon viewmodel perd des listes pour des listes déroulantes, ainsi je dois les lire en quelque sorte à ViewModel après [HttpPost] par exemple.

+0

Les listes sont-elles nécessaires pour le modèle de vue ou sont-elles simplement utilisées pour remplir des listes déroulantes? – Nkosi

+0

Je ne sais pas si j'ai bien compris votre question. Je pense qu'ils sont nécessaires pour le viewmodel parce que j'ai besoin d'eux pour remplir les listes déroulantes. Je sais que ViewData peut être utilisé à la place, mais ViewModel semble être une meilleure approche. Ces listes sont utilisées uniquement pour les listes déroulantes. – Kostrzak

+0

Si vos propriétés de collection de 'viewMod' ne sont pas liées en utilisant simplement' MyViewModel viewMod', c'est parce que vous voyez que c'est faux. Vous devriez le montrer pour que vos erreurs puissent être corrigées (regardez le html votre génération - vous devriez avoir les attributs 'name' tels que' name = "_ list1 [0] .someProperty" ',' name = "_ list1 [1]. someProperty "' etc) –

Répondre

1

Le seul travail de modelbinder consiste à lier des données de la requête (chaîne de requête ou corps de message) aux paramètres de votre méthode d'action. Donc, non, s'il n'y a pas de paramètre, le modelbinder ne fait rien avec les données.

Vous pouvez pouvez accéder aux données directement à partir de la demande, c'est-à-dire Request["list1"]. Cependant, ce sont les données brutes que le modelbinder recevra, avant même de faire le travail. En d'autres termes, vous devrez manuellement faire coercition de type ou de nouvelles choses, etc., avec ces données. Cela a l'air d'être un XY problem. Qu'est-ce que vous êtes réellement essayant de réaliser, parce qu'il y a probablement un meilleur moyen.

+0

Vous avez dit que modelbinders lier les données de la requête, mais si je crée un lieur Modal personnalisé implémentant IModelBinder, je peux passer (créer?) L'objet qui n'est pas dans la requête (je peux avoir un simple bouton sur le formulaire) et encore l'objet sera créé et passé en paramètre. Je pense que lorsque j'ajoute un paramètre à la méthode d'action POST, le classeur par défaut essaiera de trouver une requête correspondante et s'il échoue, il essaiera d'utiliser des reliures personnalisées pour créer un objet et le passer en paramètre. Ai-je bien compris? – Kostrzak

+2

Les reliures personnalisées sont une solution à la recherche d'un problème. Il y a peut-être un cas d'utilisation pour eux, mais je n'ai pas encore trouvé une seule suggestion d'utiliser un classeur de modèle personnalisé qui n'a pas pu être résolu en faisant juste les choses correctement en premier lieu. Encore une fois, veuillez préciser exactement ce que vous essayez de réaliser, et peut-être que quelqu'un peut vous dire comment le faire de manière correcte et durable. –

0

Vous pouvez utiliser la propriété ControllerBase.ViewBag pour stocker des ressources pour la vue à utiliser.

public class MyController : Controller { 

    public ActionResult SubmitNewValue() { 
     populateDropDownLists(); 

     MyViewModel model = GetDefaultViewModel(); 
     return View(model); 
    } 

    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult SubmitNewValue(MyViewModel viewMod) { 
     processMyViewModel(viewMod); 
     populateDropDownLists(); 
     return View(viewMod); 
    } 

    void populateDropDownLists() { 
     //These could be cached lists 
     ViewBag.List1 = GetList1(); 
     ViewBag.List2 = GetList1(); 
     ViewBag.List3 = GetList1(); 
    } 
} 

Et puis dans votre vue, vous pouvez accéder aux listes pour remplir vos menus déroulants

@Html.DropDownListFor(m => m.MyViewModelProperty, (IEnumerable<SelectListItem>)ViewBag.List1, "Select...", new { @class = "form-control select" }) 

Le modèle de vue ne devrait pas être chargé de stocker les listes. Étant donné que les listes sont uniquement destinées à remplir les listes déroulantes de la vue, elles doivent être séparées.

+0

Je n'ai aucun problème à transmettre des données (listes) à la vue. Je peux utiliser viewbag, viewdata, viewmodel etc. Dans votre solution, je dois créer et ajouter une méthode au contrôleur pour chaque liste dont j'ai besoin. Je ne dis pas que c'est une mauvaise pratique, mais si je peux créer un ModelBinder personnalisé qui crée une liste pour moi et que je peux utiliser dans chaque contrôleur, alors il devrait y avoir un moyen d'obtenir cet objet explicite comme ModelBinder. GetObject <>() ... – Kostrzak

+0

Alors ce que vous recherchez n'a rien à voir avec le classeur modèle. – Nkosi

+0

Puis @ChrisPratt a répondu à votre question. Vous pourriez essayer d'utiliser DI pour obtenir des listes. – Nkosi