Revalidating a modified ViewModel within a controller method?
EDIT - We're using MVC4 Dev Preview....
I'm implementing an edit page for a FishingTrip
class. FishingTrip
contains a child collection of simple Crew
objects (i.e. FishingTripID, CrewID, CrewPosition).
I'm using Jarrett Meyer's approach to add, edit and delete from the Crew
collection.
I'm using unobtrusive validation to specify that the properties of Crew
are all Required
.
My problem: when I logically-delete an item from the list (as per Jarrett's method), I don't want that item to be validated.
I have successfully tweaked the "removeRow" method on the client-side to disable unobtrusive validation for the logically-deleted item, so that the form will post despite there being an item that contains blank fields.
In my controller method [HttpPost] Edit
, ModelState.IsValid
starts off as false (as expected - because of the logically-deleted item that contains blank fields.) So I remove that item from my ViewModel.... but ModelState.IsValid
is still false.
In summary, I (think I) want to modify my ViewModel within the controller method to remove the offending item, then call some kind of "revalidate", and have ModelState.IsValid
show up as true.
Any ideas?
Solution 1:
Once you have removed the offending item(s), clear the ModelState and validate again, like so:
ModelState.Clear();
TryValidateModel(crew); // assumes the model being passed is named "crew"
Note: Be carefull when use TryValidateModel
method because this method does not validate nested object of model (As mentioned by @Merenzo).
Solution 2:
Late to the game, but still:
I was also looking for a way to validate model after doing some tweaks to it (more precisely - to the items of its nested collection) - and TryValidateModel
didn't work for me, as it doesn't process nested objects.
Finally, I settled with custom model binder:
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);
}
}
on the model class:
[ModelBinder(typeof(MyItemModelBinder))]
public class MyItemModel : IValidatableObject
{
//...
}