2010-03-02 10 views
5

Estoy tratando de crear un formulario en ASP.NET MVC2 RC 2 que se basa en un objeto de evento del calendario. El objeto tiene eventTypeId que es un System.Int32 con el que necesito rellenar a través de una lista de selección.fuertemente tipado vista con una SelectList para DropDownList mediante ViewData: No coinciden los tipos de presentar

El controlador para crear la vista inicial es:

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

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

    return View(); 
} 

El fragmento de la vista (con la cabecera) es:

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

... 

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

que se traduce el HTML de:

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

El controlador POST-aceptar es:

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

(He intentado añadir [Bind (Exclude="eventTypeId")] frente al parámetro "CalendarEvent newEvent", pero eso no cambia el comportamiento.)

Problema: Cuando envíe el formulario, me sale una excepción InvalidOperationException:

el elemento ViewData que tiene la clave 'eventTypeId' es de tipo 'System.Int32', pero tiene que ser de 'IEnumerable <SelectListItem>'.

He visto una serie de ejemplos aquí y en los blogs de MVC, pero hasta ahora no está claro cómo se supone que funciona (parece que basado en muchos ejemplos, debería funcionar como está) . ¿Necesito crear un segundo modelo que tenga una variable de tipo SelectListItem para aceptar SelectListItem y convertir el valor a System.Int32 para establecer eventTypeId? Eso parece bastante redondo.

Respuesta

7

Después de pensar en esto un poco más, pensé que tal vez necesitaba completar ViewData["eventTypeID"] en la acción del controlador que recibe los valores publicados, no solo en la acción del controlador que configura el formulario. Intenté eso y funcionó.

La acción del controlador que acepta el cargo fue alterado (sumando las dos últimas líneas en este listado):

[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"); 
     .... 

Eso no estaba claro para mí, así que espero que alguien encuentra este útil también. Comprobé el HTTP POST real con LiveHTTPHeaders plugin para Firefox y de hecho entryTypeID se contabiliza como "... & entryTypeId = 2 & ..." (que había seleccionado el segundo punto del formulario antes de enviarlo), pero no nos vuelva a cargar la lista de selección en el controlador publicado para hacer la validación?

+7

Bueno, piénsalo de esta manera. DropDownList envía un valor único al servidor. El valor que el usuario selecciona. No envía todos los valores * posibles * que se encuentran en la lista desplegable. Así no es la forma en que funciona HTML, que tal vez es algo desafortunado. Es por eso que necesita volver a llenar los datos de vista en la solicitud POST para indicar cuál es el rango de valores posibles. No necesita repoblar el valor seleccionado. – Haacked

+1

Muchas gracias por esta solución, definitivamente no es intuitiva, pero tiene sentido cuando lo piensas :) – jamiebarrow

+0

Me atrapó otra cosa no intuitiva que tenía sentido: decir que tienes 'Html.RenderAction (" LoginBox ")' y la acción 'LoginBox' tiene un GET y POST. Si envía un formulario para otra cosa no relacionada con 'LoginBox' (pero pasa a estar en la misma página a través de RenderAction) y luego devuelve la vista en caso de falla de validación, la versión POST de' LoginBox' se llama/devuelve no GET. ¡Todo esto tiene sentido, pero hay algunos ángulos difíciles! Editar: Vaya, respondió al hilo completamente equivocado aquí. – Cymen

2

Este problema se produce si el ViewData no contiene valores requeridos para todos los campos de la vista y el ViewData se devuelve a la vista.

Cuestiones relacionadas