Im working on a big MVC3 web application and have an annoyance regarding the ModelState.IsValid
method.
ModelState is being used in nearly all of my controllers so to validate the data being posted. The views are all based on ViewModels which contain different classes and these classes obviously contain properties which could be marked as [Required]
.
The problem i am having is the required properties are sometimes not required and im having to use the ModelState.Remove
method so that ModelState.IsValid
becomes true.
My question is by using ModelState.Remove
, is this the correct way of doing things or is there a more efficient approach.
Remove(KeyValuePair<String,ModelState>)Removes the first occurrence of the specified object from the model-state dictionary.
ModelState. IsValid indicates if it was possible to bind the incoming values from the request to the model correctly and whether any explicitly specified validation rules were broken during the model binding process. In your example, the model that is being bound is of class type Encaissement .
If you are getting your Model from a form and you want to manipulate the data that came from the client form and write it back to a view, you need to call ModelState. Clear() to clean the ModelState values. The reason is that normally, you want to postback to the client the form with all the errors.
Errors property and the ModelState. IsValid property. They're used for the second function of ModelState : to store the errors found in the submitted values.
Here's my solution - a RemoveFor()
extension method on ModelState
, modelled after MVC HTML helpers:
public static void RemoveFor<TModel>(this ModelStateDictionary modelState, Expression<Func<TModel, object>> expression) { string expressionText = ExpressionHelper.GetExpressionText(expression); foreach (var ms in modelState.ToArray()) { if (ms.Key.StartsWith(expressionText + ".") || ms.Key == expressionText) { modelState.Remove(ms); } } }
Here's how it's used :
if (model.CheckoutModel.ShipToBillingAddress == true) { // REUSE BILLING ADDRESS FOR SHIPPING ADDRESS ShoppingCart.ShippingAddress = ShoppingCart.BillingAddress; // REMOVE MODELSTATE ERRORS FOR SHIPPING ADDRESS ModelState.RemoveFor<SinglePageStoreModel>(x => model.CheckoutModel.ShippingAddress); }
So in answer to your question I believe there are definitely use-cases where this is the right way to do it, and a strongly typed helper like this makes it much nicer to look at - and easier to justify if you're concerned about lots of magic strings.
If you're using the same view model with a [Required]
property in two different contexts, one where the property is required and one where it isn't, then you'll need to manually alter the ModelState
as you're doing.
An alternative is to use a different view model. Perhaps have a base class with all properties except the required property in question. Then derive two view models from it, one with the property where is it required and one with the property where it is not (it's duplication, I know). You may decide to keep them entirely separate altogether and not use inheritance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With