Solución:
El error significa que el valor de CategoryList
es nulo (y como resultado el DropDownListFor()
El método espera que el primer parámetro sea de tipo IEnumerable<SelectListItem>
).
No está generando una entrada para cada propiedad de cada SelectListItem
en CategoryList
(y tampoco debería) por lo que no hay valores para el SelectList
se publican 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()
eventualmente llama al siguiente método
private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata,
string optionLabel, string name, IEnumerable<SelectListItem> selectList, bool allowMultiple,
IDictionary<string, object> htmlAttributes)
que comprueba si el 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<SelectListItem> GetSelectData(this HtmlHelper htmlHelper, string name)
que evalúa el primer parámetro de @Html.DropDownListFor()
(en este caso CategoryID
)
....
o = htmlHelper.ViewData.Eval(name);
....
IEnumerable<SelectListItem> selectList = o as IEnumerable<SelectListItem>;
if (selectList == null)
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
MvcResources.HtmlHelper_WrongSelectDataType,
name, o.GetType().FullName, "IEnumerable<SelectListItem>"));
}
Porque la propiedad CategoryID
es tipo de int
, no se puede lanzar a IEnumerable<SelectListItem>
y se lanza la excepción (que se define en el MvcResources.resx
archivar como)
<data name="HtmlHelper_WrongSelectDataType" xml:space="preserve">
<value>The ViewData item that has the key '{0}' is of type '{1}' but must be of type '{2}'.</value>
</data>
de acuerdo con la respuesta de stephens (user3559349), esto puede ser útil:
@Html.DropDownListFor(m => m.CategoryID, Model.CategoryList ?? new List<SelectListItem>(), "-Please select-")
o en ProjectVM:
public class ProjectVM
{
public ProjectVM()
{
CategoryList = new List<SelectListItem>();
}
...
}