2010-11-14 10 views
7

Tengo una clase viewmodel que contiene un par de propiedades. Básicamente, el registro actual (que el usuario está editando) y una lista de opciones (que se utiliza para completar una lista desplegable usando DropDownListFor).MVC DropDownListFor - ¿Debo volver a llenar manualmente las opciones después de que la validación falla?

Después de enviar el formulario, si el modelo no es válido, vuelvo a la vista. Entiendo que el formulario se rellena con la entrada 'rechazada' del ModelState["name"].Value.AttemptedValue, pero no estoy seguro de qué hacer con la lista de valores de la lista desplegable.

Si no hago nada, en la validación falla y regreso a la página aparece un error de 'referencia de objeto no establecido en instancia de un objeto' porque la propiedad list del viewmodel es nula. Sé que es nulo porque no estaba vinculado desde la publicación del formulario, por lo que puedo volver a llenarlo desde la base de datos antes de volver a la vista.

¿Es esa la forma correcta de hacerlo, o me falta una forma más obvia de hacer que los valores de la lista desplegable persistan?

Respuesta

10

Sí, esa es la forma correcta si la intención de devolver el mismo punto de vista de la acción POST:

  1. unen la lista de la acción de obtener de la base de datos
  2. renderizar la vista
  3. el usuario envía el formulario para la acción POST
  4. en esta acción solo obtiene el valor seleccionado, por lo que si el modelo no es válido y necesita volver a mostrar la vista debe recuperar la lista de la base de datos para completar su modelo de vista.

He aquí un ejemplo de un patrón de uso común en MVC:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     var model = new MyViewModel 
     { 
      Items = _repository.GetItems() 
     }; 
     return View(model); 
    } 

    [HttpPost] 
    public ActionResult Index(MyViewModel model) 
    { 
     if (!ModelState.IsValid) 
     { 
      // Validation failed, fetch the list from the database 
      // and redisplay the form 
      model.Items = _repository.GetItems(); 
      return View(model); 
     } 
     // at this stage the model is valid => 
     // use the selected value from the dropdown 
     _repository.DoSomething(model.SelectedValue); 
     // You no longer need to fetch the list because 
     // we are redirecting here 
     return RedirectToAction("Success", "SomeOtherController"); 
    } 
} 
+0

Gracias. Esa es prácticamente la técnica que estaba usando. Solo trabajando por mi cuenta en un proyecto que usa una nueva tecnología, ¡es bueno contrastar con una segunda opinión! – Gavin

0

Puede utilizar la función xhr Ajax para enviar sus datos, en lugar de enviar el formulario por defecto es botón de enviar.

La ventaja de esta técnica es que no necesitará volver a llenar sus listas.

En el lado del cliente y después de la llamada ajax posterior que pueda decidir hacer cualquier cosa que quiera por medio de cheque en el valor status

$.ajax({ 
    url: '@Url.Action("Index", "Controller")', 
    data: $("#form").serialize(), 
    type: 'POST', 
    success: function (data) { 
     if (data.status == "Successful") { 
      // you can redirect to another page by window.location.replace('New URL') 
     } else { 
      // you can display validation message 
     } 
    } 
}); 

Usted ActionMethod será como:

[HttpPost] 
     public JsonResult Index() 
     { 
      if (ModelState.IsValid) 
      { 
       return Json(new { status = "Success" });  
      } 
      else 
      { 
       return Json(new { status = "Fail" }); 
      } 
     } 
Cuestiones relacionadas