2009-07-16 5 views
19

La plupart des astuces sur la mise en œuvre de la validation dans ASP.NET MVC semblent se centrer autour du modèle (création de couches de service entre modèle et contrôleur ou propriétés de décoration du modèle avec attributs de validation) .Validation sur ViewModels dans ASP.NET MVC

Dans mon application, j'utilise ViewModels pour toutes les communications entre les contrôleurs et les vues.

J'ai un ViewModel pour ma page de connexion appelée 'LoginViewModel' avec une propriété appelée 'EmailAddress'. Lorsque l'utilisateur entre son adresse e-mail et clique sur Envoyer, ce ViewModel est rempli et envoyé au contrôleur, où l'adresse e-mail est validée.

Il doit s'agir d'une adresse e-mail valide et l'utilisateur doit provenir d'un domaine enregistré auprès du système.

Quel serait un moyen pratique d'ajouter une validation à cela? Dois-je mettre la validation dans le ViewModel lui-même? Ou devrait-il rester dans le contrôleur?

Répondre

5

"Dois-je mettre la validation dans le ViewModel lui-même? Ou devrait-il rester dans le contrôleur "Je suis d'accord avec Robert mais je voudrais ajouter une prise pour l'automatisation supplémentaire

Si vous regardez un outil tel que xVal, vous pouvez voir que la validation de routine (par exemple, les champs obligatoires, les numéros dans les chaînes, les chaînes qui correspondent aux expressions régulières) peuvent être automatiquement créées en décorant les champs de vos classes de données En fait, xVal peut écrire automatiquement le JavaScript pour les validations de routine afin qu'il soit effectué côté client, sans écrire de code. est-ce que cet utilisateur est membre d'un domaine enregistré dans notre base de données?)

L'utilisation de l'idiome ViewModel peut poser quelques problèmes à ce schéma Mon approche actuelle consiste à intégrer mon objet entité s dans mon modèle de vue, par ex.

public class Contact { 
    [Required] 
    string Name { get; set; } 
} 

public class ContactView { 
    public Contact Contact { get; set; } 
    public string SomeOtherViewProperty { get; set; } 
} 

puis dans le contrôleur, la validation peu profonde se produit lors de la mise à jour du modèle:

UpdateModel(contactViewModel.Contact, "Contact"); 

et les calculs nécessitant des validations plus d'informations ou plus complexes se produisent à l'intérieur de la couche modèle lui-même.

Une autre approche consiste à ne pas incorporer l'objet entité, mais simplement mapper des champs individuels entre les deux. J'ai récemment pris connaissance d'un outil appelé AutoMapper qui relie automatiquement les champs entre le domaine et les objets du modèle de vue. Il semble qu'il devrait supporter cette méthode de validation, même si je ne l'ai pas encore utilisé.

+0

Bonnes idées, Keith! En ce moment, j'ai la même stratégie que vous - l'intégration de modèles dans ViewModels. Ce que je voudrais, c'est que Model et ViewModels puissent implémenter la validation de la même manière, et qu'un framework JS tel que xVal puisse fonctionner de manière transparente avec l'un ou l'autre. Ce serait le moyen le plus flexible. Je ne pense pas que la validation devrait être exclusivement liée au modèle. – Jonathan

+0

J'ai également utilisé des modèles de vue personnalisés avec des classes de modèles incorporées, y compris xVal. Cependant, il y a des cas où j'ai besoin que mon viewmodel ne contienne qu'un sous-ensemble des propriétés du modèle. Je regarde actuellement Automapper pour cartographier ces modèles. Cela fonctionne bien, mais comment utiliser xVal dans ce scénario? Décorer le ViewModel avec l'attribut MetaData ne fonctionne pas puisque AssociatedMetadataTypeTypeDescriptionProvider renvoie si l'objet metadata contient des propriétés qui ne font pas partie du viewmodel. Si vous utilisez Automapper, j'aimerais savoir comment vous avez résolu ce problème. –

3

Les NerdDinner tutorials montrent que la validation a été effectuée dans vos classes partielles du modèle (par exemple Linq to SQL ou Entity Framework). Mais puisque vous utilisez View Models, vous pouvez y mettre la logique de validation.

La logique de validation ne va pas dans le contrôleur. Au contraire, il est accroché par le contrôleur avec une propriété de contrôle, à savoir ModelState.IsValid

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create(Dinner dinner) { 

    if (ModelState.IsValid) { 

     try { 
      dinner.HostedBy = "SomeUser"; 

      dinnerRepository.Add(dinner); 
      dinnerRepository.Save(); 

      return RedirectToAction("Details", new { id=dinner.DinnerID }); 
     } 
     catch { 
      ModelState.AddModelErrors(dinner.GetRuleViolations()); 
     } 
    } 

    return View(new DinnerFormViewModel(dinner)); 
} 

Tous les détails sont ici:

Construire le modèle
http://nerddinnerbook.s3.amazonaws.com/Part3.htm

et ici:

ViewData et ViewModel

+0

** Note: ** Pour NerdDinner mis à jour, voir ici: http://nerddinner.codeplex.com/SourceControl/changeset/view/ef63780655b0 –