ViewData элемент с ключом 'ХХХ' имеет тип System.Типа int32' но должны быть типа 'интерфейс IEnumerable '
у меня есть следующие модели представления
public class ProjectVM
{
....
[Display(Name = "Category")]
[Required(ErrorMessage = "Please select a category")]
public int CategoryID { get; set; }
public IEnumerable<SelectListItem> CategoryList { get; set; }
....
}
и следующий метод контроллера, чтобы создать новый проект и присвоить 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
}
и
@model ProjectVM
....
@using (Html.BeginForm())
{
....
@Html.LabelFor(m => m.CategoryID)
@Html.DropDownListFor(m => m.CategoryID, Model.CategoryList, "-Please select-")
@Html.ValidationMessageFor(m => m.CategoryID)
....
<input type="submit" value="Create" />
}
вид отображается правильно, но при отправке формы, я получаю следующее сообщение об ошибке
InvalidOperationException: элемент ViewData с ключом 'CategoryID' имеет тип 'System. Int32', но должен иметь тип 'IEnumerable'.
та же ошибка возникает при использовании @Html.DropDownList() метод, и если я передаю SelectList с помощью ViewBag или ViewData.
1 ответ:
ошибка означает, что значение
CategoryListравно null (и в результатеDropDownListFor()метод ожидает, что первый параметр имеет типIEnumerable<SelectListItem>).вы не генерируете входные данные для каждого свойства каждого
SelectListItemнаCategoryList(и вы не должны) так что никаких значений дляSelectListпубликуются в методе контроллера, и поэтому значениеmodel.CategoryListв методе POST этоnull. Если вы возвращаете представление, вы должны сначала переназначить значениеCategoryList, так же, как и вы в методе 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 }чтобы объяснить внутреннюю работу (исходный код может быть посмотреть здесь)
каждая перегрузка
DropDownList()иDropDownListFor()в конечном итоге вызывает следующий методprivate static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata, string optionLabel, string name, IEnumerable<SelectListItem> selectList, bool allowMultiple, IDictionary<string, object> htmlAttributes)который проверяет, если
selectList(второй параметр@Html.DropDownListFor()) составляет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; }, который, в свою очередь, называет
private static IEnumerable<SelectListItem> GetSelectData(this HtmlHelper htmlHelper, string name), который вычисляет первый параметр
@Html.DropDownListFor()(в данном случае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>")); }потому что собственность
CategoryIDis typeofint, он не может быть приведен кIEnumerable<SelectListItem>и выбрасывается исключение (которое определяется вMvcResources.resxfile as)<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>
Comments