web-dev-qa-db-fra.com

ASP.NET MVC 2 - Html.DropDownListFor confusion avec ViewModel

Je suis totalement perdu et confus sur la façon d'utiliser le nouvel assistant Html.DropDownListFor fortement typé sur ASP.NET MVC 2.0 R2

Dans la vue que j'écris:

<%= Html.DropDownListFor(m => m.ParentCategory, new SelectList(Model.Categories, "CategoryId", "Name", Model.ParentCategory), "[ None ]")%>

<%= Html.ValidationMessageFor(m => m.ParentCategory)%>

et mon objet Model est donc:

public class CategoryForm : FormModelBase
{
    public CategoryForm()
    {
        Categories = new List<Category>();

        Categories.Add(new CategoryForm.Category() {
                           CategoryId = 1, 
                           Name = "CPUs" });
        Categories.Add(new CategoryForm.Category() { 
                           CategoryId = 2, 
                           Name = "Memory" });
        Categories.Add(new CategoryForm.Category() { 
                           CategoryId = 3, 
                           Name = "Hard drives" });
    }

    // ...other props, snip... //

    public Category ParentCategory { get; set; }

    public IList<Category> Categories { get; protected set; }

    public class Category
    {
        public int? CategoryId { get; set; }
        public string Name { get; set; }
    }
}

Le problème est que lorsque je sélectionne un élément dans la liste déroulante, par exemple le premier élément, j'obtiens l'erreur ValidationMessageFor suivante "La valeur" 1 "n'est pas valide."

Je change donc la vue en ...

<%= Html.DropDownListFor(m => m.ParentCategory.**CategoryId**, 
                              new SelectList .../ snip  ) %>

Maintenant ça marche, un peu. La propriété ParentCategory dans mon ViewModel est définie avec le "CategoryId" correct, mais le "Nom" est NULL. Suis-je mieux d'avoir juste un int nullable pour la propriété ParentCategory au lieu d'un objet "Category" fortement typé?

32
Sunday Ironfoot

Je rencontrais également le même problème.

Lorsque je débogue l'action et regarde le ModelState.Values ​​[1] .Errors [0] .Exception par exemple, je vois ce qui suit:

{"La conversion des paramètres du type 'System.String' en type 'System.Collections.Generic.KeyValuePair`2 [[System.String, mscorlib, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089], [System. Int64, mscorlib, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089]] 'a échoué car aucun convertisseur de type ne peut convertir entre ces types. "} System.Exception {System.InvalidOperationException}

Dans mon scénario, ma SelectList est créée à partir d'un dictionnaire et je l'utilise à mon avis:

<%=Html.DropDownListFor(x => x.MyDictionary, 
                             new SelectList(
                                 Model.MyDictionary, 
                                 "Value", 
                                 "Key")) %>

Quand je l'ai changé en:

<%=Html.DropDownListFor(x => x.MyDictionary.Keys, // <-- changed to .Keys
                             new SelectList(
                                 Model.MyDictionary, 
                                 "Value", 
                                 "Key")) %>

Cela a fonctionné sans problèmes.

Je vous remercie.

29
Rami A.
<%= Html.DropDownListFor(m => m.ParentCategory, 
                              new SelectList(
                                  Model.Categories,
                                  "CategoryId", 
                                  "Name",
                                  Model.ParentCategory),
                             "[ None ]")%> 

Avez-vous essayé d'utiliser Model.ParentCategory.CategoryId comme dernier paramètre dans SelectList et supprimez [None] paramètre?

9
Edmon

Je me débarrasserais de

public Category ParentCategory { get; set; }

et faire un

public int? CategoryId { get; set; }

au lieu. Vous n'avez probablement besoin que de l'ID de toute façon - vous pouvez toujours rechercher l'objet réel en utilisant l'ID comme clé (en utilisant un linq/lambda sur votre liste dans votre cas).

La vue aura alors ces deux:

<%= Html.DropDownListFor(m => m.CategoryId, 
                              new SelectList(
                                  Model.Categories, 
                                  "CategoryId", 
                                  "Name", 
                                  Model.CategoryId), 
                              "[ None ]")%>

<%= Html.ValidationMessageFor(m => m.CategoryId)%>

Si la SelectList est nulle dans le ViewModel, j'ai également reçu l'erreur ci-dessus

Assurez-vous que la SelectList est définie

1
Gertjan