2010-12-05 1 views
5

J'ai ViewModel qui a un modèle et quelques propriétés supplémentaires. Il y a validation sur le modèle et sur la propriété, mais une fois exécutées, seules les validations sur Modèle sont vérifiées, la validation dans la propriété est ignorée.ASP.NET MVC La validation du modèle ne fonctionne pas sur ViewModel

Le modèle:

[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; } 
} 

Le ViewModel

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; 
    } 
} 

Le contrôleur

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 vue

@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 je soumets le formulaire en laissant le mot de passe vide, il laissera passer. Si je laisse vide les champs du client, il affiche les erreurs (sauf le champ mot de passe)

Répondre

9

C'est normal. Votre action de contrôleur POST prend Customer comme paramètre et non le modèle de vue. La validation est effectuée par le classeur du modèle. Ainsi, lorsque le classeur tente de lier l'objet Client aux paramètres de la requête, il appelle la validation. Votre action POST doit prendre le modèle de vue en paramètre si vous souhaitez que la validation soit effectuée sur ce modèle de vue. Actuellement, tout ce que vous faites avec ce modèle de vue dans l'action de publication est d'appeler le constructeur et d'appeler le constructeur ne déclenche aucune validation.

donc votre action POST devrait devenir:

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

Remarquez que vous n'avez pas besoin de passer le mot de passe en tant que deuxième argument de l'action telle qu'elle est déjà partie de votre modèle de vue.

+0

Cela semble logique et peut m'aider à le réparer. Je vais faire la validation des autres propriétés dans le contrôleur par séparé jusqu'à trouver la meilleure solution pour utiliser la validation du modèle pour ce cas. Merci beaucoup. – Nestor

+0

Comment rendre la vue pour passer un ViewModel au contrôleur de poste? Je l'avais déjà essayé et montre une erreur "nullable parameter" puisque le formulaire reçoit le ViewModel mais quand il revient, il le décompose vers chaque modèle dans le ViewModel pour qu'il ne puisse pas correspondre à la signature sur le contrôleur, et le contrôleur Le paramètre ViewModel, qui me force dans Post Controller, à obtenir chaque modèle comme paramètre séparé au lieu d'un seul paramètre pour le ViewModel. – Nestor

+0

@Nestor, pour que la vue passe un ViewModel à un contrôleur, vous pouvez inclure un '

' dans cette vue et placer à l'intérieur des champs de texte correspondant aux propriétés de votre ViewModel qui seront transmises. N'oubliez pas que seuls les éléments envoyés dans la requête seront liés à ViewModel. –

0

Je crois que c'est parce que le setter sur votre propriété de mot de passe est private set. Tous les setters sur le reste de vos champs clients sont des setters publics. Lorsqu'une propriété ne dispose pas d'une vérification Setter pour une valeur valide n'est pas requise.

+0

Lorsque le constructeur est appelé, le constructeur est chargé de définir ces propriétés privées, pas besoin d'accéder à ces propriétés de l'extérieur de la classe. Raison est comme Darin dit à propos de seulement Model est appelé, pas ViewModel donc pas de liaison pour ViewModel donc pas de validation déclenchée. – Nestor

Questions connexes