2010-07-24 15 views
0

J'ai une application MVC Asp.NET dans lequel j'utilise des annotations de données pour ajouter la validation à certains champs:DataAnnotations [Obligatoire] attribut ne provoque pas d'exception à jeter

[Required] 
    [DisplayName("Course Name")] 
    string Name { get; set; } 

Toutefois, cela ne semble pas travailler comme je m'y attendais. Fondamentalement Si la page contient d'autres erreurs que je vérifie manuellement et lancez un nouveau RuleViolation(), alors la violation requise est montrée dans le résumé de validation. Si la violation requise est la seule erreur, elle n'est pas affichée.

Mon contrôleur a ce code dans le:

 catch (Exception ex) 
     { 
      ModelState.AddModelError("", ex.Message); 
      ModelState.AddRuleViolations(courseViewModel.Course.GetRuleViolations()); 
      return View(courseViewModel); 
     } 

Mais étant donné que la violation requise est de ne pas jeter, je ne vais jamais ici. Dois-je faire quelque chose que je ne connais pas pour intercepter les erreurs provoquées par la violation de DataAnnotation?

Merci pour toute aide

Edit:

Voici l'action du contrôleur:

[HttpPost] 
    [ValidateInput(true)] 
    public ActionResult Edit(int id, CourseViewModel courseViewModel) 
    { 

     var oldCourse = _eCaddyRepository.GetCourse(id); 

     if (courseViewModel.Course == null) 
     { 
      return View("NotFound", string.Format("Course {0} Not Found", id)); 
     } 

     try 
     { 
      courseViewModel.Update(oldCourse); 
      _eCaddyRepository.SubmitChanges(); 

      return RedirectToAction("Index", "Course"); 
     } 
     catch (Exception ex) 
     { 
      ModelState.AddModelError("", ex.Message); 
      ModelState.AddRuleViolations(courseViewModel.Course.GetRuleViolations()); 
      return View(courseViewModel); 
     } 
    } 

Où mise à jour est:

public class CourseViewModel : BaseViewModel 
{ 
    public Course Course { get; set; } 

    public void Update(Course oldCourse) 
    { 
     oldCourse.Name = this.Course.Name != null ? this.Course.Name.Trim() : string.Empty; 
     oldCourse.Postcode = this.Course.Postcode != null ? this.Course.Postcode.Trim() : string.Empty; 

     for (var i = 0; i < 18; i++) 
     { 
      oldCourse.Holes[i].Par = this.Course.Holes[i].Par; 
      oldCourse.Holes[i].StrokeIndex = this.Course.Holes[i].StrokeIndex; 
     } 
    } 
} 

EDIT: Code final qui fonctionne et valide comme prévu en utilisant des notifications de données. Merci à mare.

[HttpPost] 
    [ValidateInput(true)] 
    public ActionResult Edit(int id, CourseViewModel courseViewModel) 
    { 
     var oldCourse = _eCaddyRepository.GetCourse(id); 

     if (courseViewModel.Course == null) 
     { 
      return View("NotFound", string.Format("Course {0} Not Found", id)); 
     } 

     if (ModelState.IsValid) 
     { 
      try 
      { 
       courseViewModel.Update(oldCourse); 
       _eCaddyRepository.SubmitChanges(); 
       return RedirectToAction("Index", "Course"); 
      } 
      catch (Exception ex) 
      { 
       ModelState.AddModelError("", ex.Message); 
      } 
     } 

     // Return Model with errors 
     ModelState.AddRuleViolations(courseViewModel.Course.GetRuleViolations()); 
     return View(courseViewModel); 
    } 
+0

Cela dépend du code de votre contrôleur, en particulier de la mise à jour du modèle. Pouvez-vous poster la méthode d'action complète? – Jon

+0

Bonjour Jon, merci pour votre réponse. J'ai modifié le post original pour inclure l'action. Je l'ai fait comme ceci pour éviter un problème que j'avais avec Linq à Sql lors de la mise à jour. J'aimerais entendre s'il y a un meilleur moyen? –

+0

Les trois lignes de code de votre bloc try..catch n'ont rien à voir avec Model Validation et DataAnnotations jointes à votre modèle - ici, vous essayez seulement d'exécuter ces trois phrases et si elles fonctionnent bien (et je suppose qu'elles le font car ils n'ont pas de logique interne pour vérifier la validité du modèle) alors aucune exception n'est levée. Ce dont vous avez besoin est ModelState.IsValid, voir ma réponse. – mare

Répondre

3

Je me demande comment personne ne fait autre ceci (jfar était proche, mais son libellé était de si chrisp_68 probablement ne comprenaient pas ce jfar voulu dire des violations d'état du modèle), mais il vous manque ce de votre contrôleur:

 if (ModelState.IsValid) // this check for model validity, not try..catch block 
     { 
      // do your stuff here, update to the datastore and return another view 
     } 

     // you can add additional Model State errors here manually if you wish 
     // with AddModelError() like you do it now 
     return View(editing); // return the same view with errors 

il est donc ModelState.IsValid vérifier que vous avez besoin, car DataAnnotations n'effectue pas lancer d'exception par eux-mêmes. EDIT: En fait, pour être précis, DataAnnotations ne fait pas de lancement d'exception car cela aurait un sens, car cela briserait l'exécution de votre application, ce que bien sûr vous ne voulez pas. Vous voulez revenir à la même vue et donner à l'utilisateur une chance de corriger ses erreurs.

D'autre part, vous pouvez toujours avoir try..catch bloc à l'intérieur du si (ModelState.IsValid) pour attraper le REAL exception comme défaut d'écrire sur le disque ou de ne pas stocker la base de données ou d'insérer dans nulls Colonnes DB où aucun null n'est autorisé, etc.

HTH

+0

Merci beaucoup pour votre aide sur tout le monde. Mare, vous êtes absolument correct dans ce que vous dites ci-dessus. J'ai fait ces changements et tout fonctionne parfaitement maintenant. Merci beaucoup. J'ai également montré le code final ci-dessus pour toute personne ayant des problèmes similaires. –

+0

Si les annotations de données ne lancent pas d'exception, que font-elles alors? Est-ce qu'ils ajoutent l'erreur dans le dictionnaire d'états du modèle? Cela n'a pas de sens car vous pouvez faire des annotations de données dans des applications non-mvc. – Chev

+0

s'il vous plaît jeter un oeil à cette question sur la façon dont le travail DA et les détails sur MVC http://stackoverflow.com/questions/6496705/how-do-data-annotations-work – mare

1

Il n'y a rien dans MVC2 qui déclencherait une exception en raison d'un champ [Obligatoire].

Vous obtenez des violations d'état du modèle, c'est tout. Assez sûr que les exceptions sont seulement lancées à partir d'un appel manuel à ModelBinder lorsque vous essayez de lier "Joel Atwood" à un champ DateTime.

+0

Savez-vous comment les violations d'état du modèle finissent habituellement par s'afficher. J'ai un Html.ValidationSummary et ils sont affichés là, mais seulement si le code passe par la capture ci-dessus. –

0

Sur la propriété de la classe il y a u mettre l'annotation de données, espace de noms doit être « YouProject.Model »

+0

Merci pour le commentaire, oui je l'ai fait et cela fonctionne mais seulement si une exception de règles différentes est levée –