2009-01-04 10 views
6

J'ai un contrôleur avec deux actions:ASP.NET MVC Form repopulation

[AcceptVerbs("GET")] 
    public ActionResult Add() 
    { 
     PrepareViewDataForAddAction(); 
     return View(); 
    } 


[AcceptVerbs("POST")] 
    public ActionResult Add([GigBinderAttribute]Gig gig, FormCollection formCollection) 
    { 
     if (ViewData.ModelState.IsValid) 
     { 
      GigManager.Save(gig); 
      return RedirectToAction("Index", gig.ID); 
     } 
     PrepareViewDataForAddAction(); 
     return View(gig); 
    } 

Comme vous pouvez le voir, lorsque le formulaire affiche ses données, l'action Ajouter utilise un GigBinder (Un implemenation de IModelBinder)

Dans ce classeur j'ai:

if (int.TryParse(bindingContext.HttpContext.Request.Form["StartDate.Hour"], out hour)) 
     { 
      gig.StartDate.Hour = hour; 
     } 
     else 
     { 
      bindingContext.ModelState.AddModelError("Doors", "You need to tell us when the doors open"); 
     } 

Le formulaire contient une zone de texte avec id "StartDate.Hour".

Comme vous pouvez le voir ci-dessus, le test GigBinder vérifie que l'utilisateur a tapé un entier dans la zone de texte avec l'ID "StartDate.Hour". Sinon, une erreur de modèle est ajoutée au modèle en utilisant AddModelError. Puisque la propriété gigs gigs.StartDate.Hour est fortement typée, je ne peux pas définir sa valeur, par exemple, "TEST" si l'utilisateur a tapé ceci dans la zone de texte des formulaires.

Par conséquent, je ne peux pas définir la valeur de gigs.StartDate.Hour puisque l'utilisateur a entré une chaîne plutôt qu'un nombre entier. Comme l'action Ajouter renvoie la vue et transmet le modèle (return View (gig);) si l'état model n'est pas valide, lorsque le formulaire est réaffiché avec des mssages de validation, la valeur "TEST" n'est pas affichée dans le zone de texte. Au lieu de cela, ce sera la valeur par défaut de gig.StartDate.Hour.

Comment contourner ce problème? Je suis vraiment coincé!

Répondre

1

Pourriez-vous faire dans votre méthode PrepareViewDataForAddAction? ..

if (!ViewData.ModelState.IsValid) 
    { 
     ViewData["StartDate.Hour"] = "Error"; 
    } 

Les autres champs du formulaire renseignera toujours en fonction des propriétés de l'objet Gig.

1

Je pense que vous devez d'abord effectuer une validation de base côté client. ne lui permettent pas de publier sur le serveur.

2

Je pense que le problème est que votre ViewModel ne correspond pas suffisamment à votre View. Il est très important dans MVC que votre ViewModel corresponde le mieux possible à votre vue.

Dans votre ViewModel, vous supposez un entier, mais dans votre View vous utilisez un TextBox pour rendre la propriété, ce qui autorisera tout type de texte. Il y a un décalage ici et les difficultés que vous rencontrez en essayant de les cartographier sont un symptôme de l'inadéquation.

Je pense que vous devez soit: 1.
Modifier le type de la propriété ViewModel à chaîne, puis faire la validation dans votre contrôleur pour assurer la chaîne saisie est en fait un numéro ou:
2. Modifiez le contrôle que la Voir les rendus à un contrôle qui permettra seulement d'entrer un nombre via un contrôle personnalisé ou une validation Javascript (comme @Qun Wang recommande)

Personnellement, je recommande l'option 1. De cette façon, le ViewModel ne dépend pas de la Voir l'implémentation