Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it correct way to use ModelState.Remove to deal with ModelState?

Tags:

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.

like image 386
Hesky Avatar asked Jul 27 '11 10:07

Hesky


People also ask

What does ModelState remove do?

Remove(KeyValuePair<String,ModelState>)Removes the first occurrence of the specified object from the model-state dictionary.

What is ModelState IsValid method where we use it?

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 .

How do I clear ModelState errors?

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.

Which property is used to determine an error in ModelState?

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.


2 Answers

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.

like image 92
Simon_Weaver Avatar answered Sep 28 '22 18:09

Simon_Weaver


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.

like image 31
Russ Cam Avatar answered Sep 28 '22 18:09

Russ Cam