web-dev-qa-db-fra.com

Revalider un ViewModel modifié dans une méthode de contrôleur?

[~ # ~] modifier [~ # ~] - Nous utilisons MVC4 Dev Preview ....

J'implémente une page d'édition pour une classe FishingTrip. FishingTrip contient une collection enfant de simples Crew objets (par exemple FishingTripID, CrewID, CrewPosition).

J'utilise approche de Jarrett Meyer pour ajouter, éditer et supprimer de la collection Crew. J'utilise une validation discrète pour spécifier que les propriétés de Crew sont toutes Required.

Mon problème: lorsque je supprime logiquement un élément de la liste (selon la méthode de Jarrett), je ne veux pas que cet élément soit validé.

J'ai réussi à modifier la méthode "removeRow" côté client pour désactiver la validation discrète de l'élément supprimé logiquement, de sorte que le formulaire soit publié malgré la présence d'un élément contenant des champs vides.

Dans ma méthode de contrôleur [HttpPost] Edit, ModelState.IsValid commence comme faux (comme prévu - en raison de l'élément supprimé logiquement qui contient des champs vides.) Je supprime donc cet élément de mon ViewModel .... mais ModelState.IsValid est toujours faux.

En résumé, je (je pense) vouloir modifier mon ViewModel dans la méthode du contrôleur pour supprimer l'élément incriminé, puis appeler une sorte de "revalider" et avoir ModelState.IsValid apparaît comme vrai.

Des idées?

53
Merenzo

Une fois que vous avez supprimé les éléments incriminés, effacez ModelState et validez à nouveau, comme suit:

ModelState.Clear();
TryValidateModel(crew);  // assumes the model being passed is named "crew"

Note: Soyez prudent lorsque vous utilisez la méthode TryValidateModel car cette méthode ne valide pas l'objet imbriqué du modèle (comme mentionné par @Merenzo).

125
counsellorben

Tard dans le jeu, mais quand même: je cherchais également un moyen de valider le modèle après en lui apportant quelques modifications (plus précisément - aux éléments de sa collection imbriquée) - et TryValidateModel n'a pas fonctionné pour moi, car il ne traite pas les objets imbriqués.

Enfin, je me suis installé avec un classeur de modèle personnalisé:

public class MyItemModelBinder : DefaultModelBinder
{
    protected override void OnModelUpdated(
        ControllerContext controllerContext, 
        ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(MyItemModel))
        {
            MyItemModel item = (MyItemModel)bindingContext.Model;
            //do required tweaks on model here 
            //(I needed to load some additional data from DB)
        }
        //validation code will be called here, in OnModelUpdated implementation
        base.OnModelUpdated(controllerContext, bindingContext);
    }
}

sur la classe modèle:

[ModelBinder(typeof(MyItemModelBinder))]
public class MyItemModel : IValidatableObject
{
    //...
}
2
lxa