2010-05-25 5 views
0

Dans mon interface I ont une liste de zones de texte, quelque chose comme ceci: http://screencast.com/t/YjIxNjUyNmUASP.Net MVC 2 - ModelBinding et Dictionnaire <int, int>

Le nombre de zones de texte est inconnu car chacun d'eux est associé à un modèle. Dans ma page, l'objectif est d'associer un nombre à certains de ces modèles.

Voici un exemple de code HTML:

<% // loop on the templates 
    foreach(ITemplate template in templates) 
    { 
     // get the content from the input dictionary 
     int val; 
     content.TryGetValue(template.Id, out val); 
     // convert it as a string 
     string value = ((val > 0) ? val.ToString() : string.Empty); 

     // compute the element name/id (for dictionary binding) 
     string id = ?????????? 
     string name = ?????????????? 
%> 
     <label for="<%= name %>"><%= template.Name %></label> 
     <input type="text" id="<%= id %>" name="<%= name %>" value="<%= value %>" /> 
     <br /> 
<% } 
%> 

Ce que je pense, dans mon contrôleur, est d'obtenir un IDictionary où le premier int est l'ID de modèle, et l'autre est le nombre donné par l'utilisateur .

Voici ce que je veux:

public ActionResult Save(int? id, Dictionary<int, int> countByTemplate) 

J'ai essayé beaucoup de choses, mais rien ne fonctionnait. J'ai essayé de lire les sources, mais c'est un labyrinthe, et je suis en train d'essayer d'obtenir des informations sur la liaison du modèle.

Questions:

  • est-il une bonne sur la façon dont la ressource modelbinding fonctionne? Je voudrais quelque chose d'exhaustif, j'en ai marre des 84093043 blogs qui parlent d'un exemple précis donné.
  • comment puis-je construire mon HTML, en utilisant pour obtenir un IDictionary (ou même un IDictionary dans l'action de mon contrôleur?

Merci beaucoup pour votre aide

Répondre

1

Ok ... Merci à Levi j'ai pu obtenir une solution. Pas le plus propre un, mais il fonctionne.

Le code HTML doit être écrit de cette façon:

<% 
int counter = 0; 
// loop on the templates 
foreach(ITemplate template in templates) 
{ 
     // get the value as text 
     int val; 
     content.TryGetValue(template.Id, out val); 
     var value = ((val > 0) ? val.ToString() : string.Empty); 

     // compute the element name (for dictionary binding) 
     string id = "cbts_{0}".FormatMe(template.Id); 
     string dictKey = "cbts[{0}].Key".FormatMe(counter); 
     string dictValue = "cbts[{0}].Value".FormatMe(counter++); 
%> 
     <input type="hidden" name="<%= dictKey %>" value="<%= template.Id %>" /> 
     <input type="text" id="<%= id %>" name="<%= dictValue %>" value="<%= value %>" /> 
     <label for="<%= id %>"><%= template.Name %></label> 
     <br /> 
<% } 
%> 

je devais ajouter un champ caché pour stocker la valeur. J'ai introduit un compteur 'faux' juste pour faire une boucle sur le dictionnaire comme ASP.Net MVC le veut. En conséquence, j'ai obtenu un dictionnaire rempli de mes valeurs et '0' lorsque la zone de texte est vide.

Un autre problème est apparu: le ModelState a été considéré comme non valide car «une valeur est requise». Je ne veux pas que mes valeurs soient requises, mais en regardant le code modelbinder, je n'ai pas trouvé un moyen de dire au classeur qu'une valeur n'est PAS requise.

Je dupé le ModelState dans mon contrôleur, en supprimant toute erreur, comme ceci:

public ActionResult Save(int? id, Dictionary<int, int> cbts) 
{ 
    // clear all errors from the modelstate 
    foreach(var value in this.ModelState.Values) 
     value.Errors.Clear(); 

Eh bien ... Je suis effectivement une solution, mais le HTML est une sorte de laide maintenant, et contre-intuitif (en utilisant un index pour boucler sur une collection non-indexée ??). Et j'ai besoin de tromper chaque fois que je vais utiliser ce type de liaison pour que tout fonctionne correctement.

Donc, je vais maintenant ouvrir un nouveau post pour faire quelque chose de mieux. Ici, il est: ASP.Net MVC 2 - better ModelBinding for Dictionary<int, int>

EDIT - Il existe une solution plus propre, grâce à Pavel Chuchuva.

Dans le code du contrôleur, utilisez un int null comme valeur pour le dictionnaire. Un peu plus de code à ajouter, mais beaucoup plus propre.

public ActionResult Save(int? id, Dictionary<int, int?> cbts) 
{ 
    // this is our final dictionary<int, int> 
    Dictionary<int, int> cbtsFinal = new Dictionary<int, int>(); 
    // loop on the dicitonary with nullable values 
    foreach(var key in cbts.Keys) 
    { 
     // if we have a value 
     if(cbts[key].HasValue) 
      // then put it in the final dictionary 
      cbtsFinal.Add(key, cbts[key].Value); 
    } 
+0

Essayez 'ActionResult publique Save (int? Id, Dictionnaire CBT)' –

+0

Merci, cela vaut mieux! – Mose

Questions connexes