El elemento ViewData que tiene la clave ‘XXX’ es del tipo ‘System.Int32’ pero debe ser del tipo ‘IEnumerable ‘

Tengo el siguiente modelo de vista

public class ProjectVM { .... [Display(Name = "Category")] [Required(ErrorMessage = "Please select a category")] public int CategoryID { get; set; } public IEnumerable CategoryList { get; set; } .... } 

y el siguiente método de controlador para crear un nuevo proyecto y asignar una Category

 public ActionResult Create() { ProjectVM model = new ProjectVM { CategoryList = new SelectList(db.Categories, "ID", "Name") } return View(model); } public ActionResult Create(ProjectVM model) { if (!ModelState.IsValid) { return View(model); } // Save and redirect } 

y en la vista

 @model ProjectVM .... @using (Html.BeginForm()) { .... @Html.LabelFor(m => m.CategoryID) @Html.DropDownListFor(m => m.CategoryID, Model.CategoryList, "-Please select-") @Html.ValidationMessageFor(m => m.CategoryID) ....  } 

La vista se muestra correctamente, pero al enviar el formulario, aparece el siguiente mensaje de error

InvalidOperationException: el elemento ViewData que tiene la clave ‘CategoryID’ es del tipo ‘System.Int32’ pero debe ser del tipo ‘IEnumerable ‘.

Se produce el mismo error al utilizar el @Html.DropDownList() y si paso la Lista de selección usando un ViewBag o ViewBag .

El error significa que el valor de CategoryList es nulo (y como resultado, el método DropDownListFor() espera que el primer parámetro sea del tipo IEnumerable ).

No está generando una entrada para cada propiedad de cada elemento SelectListItem en CategoryList (y tampoco debería hacerlo), por lo que no se publican valores para SelectList en el método del controlador, y por lo tanto el valor de model.CategoryList en el método POST es null . Si devuelve la vista, primero debe reasignar el valor de CategoryList , tal como lo hizo en el método GET.

 public ActionResult Create(ProjectVM model) { if (!ModelState.IsValid) { model.CategoryList = new SelectList(db.Categories, "ID", "Name"); // add this return View(model); } // Save and redirect } 

Para explicar el funcionamiento interno (el código fuente se puede ver aquí )

Cada sobrecarga de DropDownList() y DropDownListFor() finalmente llama al siguiente método

 private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata, string optionLabel, string name, IEnumerable selectList, bool allowMultiple, IDictionary htmlAttributes) 

que verifica si selectList (el segundo parámetro de @Html.DropDownListFor() ) es null

 // If we got a null selectList, try to use ViewData to get the list of items. if (selectList == null) { selectList = htmlHelper.GetSelectData(name); usedViewData = true; } 

que a su vez llama

 private static IEnumerable GetSelectData(this HtmlHelper htmlHelper, string name) 

que evalúa el primer parámetro de @Html.DropDownListFor() (en este caso, @Html.DropDownListFor() CategoryID )

 .... o = htmlHelper.ViewData.Eval(name); .... IEnumerable selectList = o as IEnumerable; if (selectList == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, MvcResources.HtmlHelper_WrongSelectDataType, name, o.GetType().FullName, "IEnumerable")); } 

Dado que la propiedad CategoryID es typeof int , no se puede convertir a IEnumerable y se IEnumerable la excepción (que se define en el archivo MvcResources.resx como)

  The ViewData item that has the key '{0}' is of type '{1}' but must be of type '{2}'.