2010-12-05 35 views
5

Tengo ViewModel que tiene dentro de un Modelo y algunas propiedades adicionales. Hay validación en el modelo y en la propiedad, pero cuando se ejecuta, solo se verifica la validación en el modelo, se ignora la validación en la propiedad.ASP.NET MVC La validación del modelo no funciona en ViewModel

El Modelo:

[MetadataType(typeof(Customer_Validation))] 
public partial class Customer 
{ 
} 

public class Customer_Validation 
{ 
    [Required(ErrorMessage="Please enter your First Name")] 
    public string FirstName { get; set; } 

    [Required(ErrorMessage = "Please enter your Last name")] 
    public string LastName { get; set; } 

    [Required(ErrorMessage = "Sorry, e-mail cannot be empty")] 
    [Email(ErrorMessage="Invalid e-mail")] 
    public string Email { get; set; } 
} 

El modelo de vista

public class RegisterViewModel 
{ 
    public Customer NewCustomer { get; private set; } 

    [Required(ErrorMessage="Required")] 
    public string Password { get; private set; } 

    public RegisterViewModel(Customer customer, string password) 
    { 
     NewCustomer = customer; 
     Password = password; 
    } 
} 

El controlador

public ActionResult Create() 
{ 
    Customer customer = new Customer();  
    RegisterViewModel model = new RegisterViewModel(customer, "");  
    return View(model); 
} 

[HttpPost] 
public ActionResult Create(Customer newCustomer, string password) 
{ 
    if (ModelState.IsValid) 
    { 
     try 
     { 
      // code to save to database, redirect to other page 
     } 
     catch 
     { 
      RegisterViewModel model = new RegisterViewModel(newCustomer, password); 
      return View(model); 
     } 
    } 
    else 
    { 
     RegisterViewModel model = new RegisterViewModel(newCustomer, password); 
     return View(model); 
    } 
} 

La vista

@using (Html.BeginForm()) 
{ 
    <table> 
    <tr> 
    <td>First Name:</td> 
    <td>@Html.TextBoxFor(m => m.NewCustomer.FirstName)</td> 
    <td>@Html.ValidationMessageFor(m => m.NewCustomer.FirstName)</td> 
    </tr> 
    <tr> 
    <td>Last Name:</td> 
    <td>@Html.TextBoxFor(m => m.NewCustomer.LastName)</td> 
    <td>@Html.ValidationMessageFor(m => m.NewCustomer.LastName)</td> 
    </tr> 
    <tr> 
    <td>E-mail:</td> 
    <td>@Html.TextBoxFor(m => m.NewCustomer.Email)</td> 
    <td>@Html.ValidationMessageFor(m => m.NewCustomer.Email)</td> 
    </tr> 
    <tr> 
    <td>Password:</td> 
    <td>@Html.TextBoxFor(m => m.Password)</td> 
    <td>@Html.ValidationMessageFor(m => m.Password)</td> 
    </tr> 
    </table> 

    <input type="submit" value="Register" /> 
} 

Si envío el formulario dejando la contraseña vacía, déjenla pasar. Si dejo vacíos los campos del Cliente, muestra los errores (excepto el campo de contraseña)

Respuesta

9

Eso es normal. Su acción de controlador POST toma Customer como parámetro y no como el modelo de vista. La validación es realizada por el archivador de modelo, por lo que cuando el archivador de modelo intente vincular el objeto Cliente a partir de los parámetros de solicitud invocará la validación. Su acción POST necesita tomar el modelo de vista como parámetro si desea que la validación se realice en este modelo de vista. Actualmente, todo lo que hace con este modelo de vista dentro de la acción de publicación es llamar al constructor y llamar al constructor no desencadena ninguna validación.

Por lo que su acción POST debe convertirse en:

[HttpPost] 
public ActionResult Create(RegisterViewModel newCustomer) 
{ 
    if (ModelState.IsValid) 
    { 
     // code to save to database, redirect to other page 
    } 
    else 
    { 
     return View(newCustomer); 
    } 
} 

Note como usted no necesita pasar la contraseña como argumento segunda acción como ya es parte de su modelo de vista.

+0

Eso suena lógico y puede ayudarme a solucionarlo. Haré la validación de otras propiedades dentro del controlador por separado hasta encontrar la mejor solución para usar la validación del modelo para este caso. Muchas gracias. – Nestor

+0

¿Cómo se hace que la Vista pase un ViewModel al controlador de correos? Lo había intentado antes y muestra un error de "parámetro de nullable" ya que el formulario recibe ViewModel pero cuando se publica, lo descompone en cada modelo dentro del ViewModel, por lo que no puede coincidir con la firma en el controlador posterior, y luego el controlador establece null en el Parámetro de ViewModel, que me obliga en el controlador posterior a obtener cada modelo como parámetro independiente en lugar de un único parámetro para ViewModel. – Nestor

+0

@Nestor, para hacer que una vista pase un ViewModel a un controlador, puede incluir un '

' en esta vista y dentro colocar campos de texto correspondientes a las propiedades de su ViewModel que se pasarán. Recuerde que solo lo que se envía en la solicitud estará vinculado a ViewModel. –

0

Creo que esto se debe a que el ajustador en su propiedad de contraseña está configurado en private set. Todos los implantadores en el resto de los campos de sus clientes son instaladores públicos. Cuando una propiedad no tiene una inspección setter para un valor válido no es necesario.

+0

Cuando el modelo está encuadernado se llama al constructor, el constructor se encarga de establecer esas propiedades privadas, no es necesario acceder a esas propiedades desde fuera de la clase. La razón es como Darin dice que solo se llama a Model, no ViewModel por lo que no se vincula a ViewModel, por lo que no se activa la validación. – Nestor

Cuestiones relacionadas