Строго типизированное представление с SelectList для DropDownList через ViewData: несоответствие типов при отправке - PullRequest
5 голосов
/ 02 марта 2010

Я пытаюсь создать форму в ASP.NET MVC2 RC 2, основанную на объекте события календаря. Объект имеет eventTypeId, который является System.Int32, который мне нужно заполнить с помощью списка выбора.

Контроллер для создания начального вида:

[WAuthorize]
public ActionResult AddCalendarEvent()
{
    CalendarEventTypesManager calendarEventTypesManager = 
        new CalendarEventTypesManager();

    ViewData["eventTypeId"] = new SelectList(
        calendarEventTypesManager.SelectAll(), "Id", "Type");

    return View();
}

Фрагмент представления (с заголовком):

<%@ Page Title="" Language="C#" 
    MasterPageFile="~/Views/Shared/Site.Extranet.master"
    Inherits="System.Web.Mvc.ViewPage<SomeProject.Models.CalendarEvent>" %>

...

<p><%= Html.DropDownList("eventTypeId") %></p>

Что приводит к HTML:

<p>
<select id="eventTypeId" name="eventTypeId">
    <option value="1">All school activities</option> 
    <option value="2">All school event</option> 
</select>
</p> 

POST-принимающий контроллер:

[WAuthorize]
// TODO research some more
[ValidateInput(false)]              
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public ActionResult AddCalendarEvent(CalendarEvent newEvent)
{
    ...

(я пытался добавить [Bind (Exclude="eventTypeId")] перед параметром "CalendarEvent newEvent", но это не меняет поведения.)

Проблема: при отправке формы я получаю исключение InvalidOperationException:

Элемент ViewData, имеющий ключ 'eventTypeId' имеет тип 'System.Int32', но должен иметь тип 'IEnumerable .

Я посмотрел несколько примеров здесь и в блогах MVC, но пока неясно, как это должно работать (похоже, основываясь на многих примерах, оно должно работать как есть). Нужно ли создавать вторую модель с переменной типа SelectListItem для принятия SelectListItem и преобразования значения в System.Int32 для фактической установки eventTypeId? Это кажется довольно круглым.

Ответы [ 2 ]

7 голосов
/ 02 марта 2010

Подумав об этом еще немного, я подумал, что, возможно, мне нужно было заполнить ViewData["eventTypeID"] в действии контроллера, которое получает опубликованные значения, а не только в действии контроллера, которое устанавливает форму. Я попробовал это, и это сработало.

Действие контроллера, которое принимает POST, было изменено (добавление двух последних строк в этом списке):

    [WAuthorize]
    [ValidateInput(false)]              // TODO research some more
    [AcceptVerbs(HttpVerbs.Post)]
    [ValidateAntiForgeryToken]
    public ActionResult AddCalendarEvent(CalendarEvent newEvent)
    {
        CalendarEventTypesManager calendarEventTypesManager = new CalendarEventTypesManager();
        ViewData["eventTypeId"] = new SelectList(calendarEventTypesManager.SelectAll(), "Id", "Type");
        ....

Это было не ясно мне, так что, надеюсь, кто-то еще найдет это полезным. Я проверил фактический POST HTTP с плагином LiveHTTPHeaders для Firefox, и действительно, entryTypeID публикуется как «... & entryTypeId = 2 & ...» (перед отправкой я выбрал второй элемент в форме), но мы перезагружаем список выбора в отправленный контроллеру для проверки?

2 голосов
/ 18 ноября 2010

Эта проблема возникает, если ViewData не содержит обязательных значений для всех полей в представлении и ViewData публикуется обратно в представление.

...