MVC3 Remove ModelState Errors
Asked Answered
P

7

92

I've got a situation where I'm uploading an image the user has selected from his local file system. My Form in my view, basically has two submit buttons. One is used to Submit the form normally, and all validation executes. The 2nd is only for uploading the image, in which case I don't want to validate yet.

I managed to turn off Client Side validation by giving my 'Upload Image' submit button an a class value of "style-name cancel" , so

<input type="submit" name="UploadImageButton" value="Upload Image" class="style-name cancel" /> 

Now, when I post back, my model has a property UploadImageButton, when this button is clicked, it populates this property (Name of the input matches the Property). This way, I know whether the form was submitted by my true Submit button or by the UploadImageButton.

My question is this... How can I turn off ServerSide validation? I don't want the Validation Summary info showing up when the user clicks this button. I know you can add custom model errors using this

ModelState.AddModelError("{key}", "{error msg}");

I'm looking for a means to Remove Model Errors. Is this possible?

EDIT:

Here is what I came up with:

foreach (var key in ModelState.Keys.ToList().Where(key => ModelState.ContainsKey(key))) {
     //ModelState.Remove(key); //This was my solution before
     ModelState[key].Errors.Clear(); //This is my new solution. Thanks bbak
}
Pulvinus answered 14/9, 2011 at 22:59 Comment(5)
Why are you doing a Where(key => ModelState.Keys.Contains(key))? It seems that the Where clause is redundant, because each key in ModelState.Keys will have its ModelState.Keys.Contains(key) return true.Mayworm
I've updated the question and the text, to use the shorter method on the ModelState.ContainsKey, although your wrong in your assumption. These are doing the same thing.Pulvinus
Sorry, I may have explained poorly or misunderstood your reply. You're right that ModelState.ContainsKey(key) and ModelState.Contains(key) do the same thing, but my point is that all the values in ModelState.Keys.ToList() will by nature be contained in ModelState, so the entire Where clause is redundant and will slow down performance. Minor thing, though.Mayworm
That was ReSharper throwing that together. Thanks for pointing that out.Pulvinus
Just notice the way you find out which button was the source of the submit. In the ViewModel you don't have to have this property. Just add a FormCollection parameter to the Controller: public ActionResult Index(YourViewModelClass model, FormCollection formCollection). And check if the button name is in it: if (formCollection["UploadImageButton"] != null). I think it's better when you have more submit button.Rosalia
S
162

You can remove model errors by doing something like this:

if (ModelState.ContainsKey("{key}"))
    ModelState["{key}"].Errors.Clear();
Soulsearching answered 14/9, 2011 at 23:30 Comment(3)
Just in case anyone was wondering, this also affects ModelState.IsValidBacksheesh
strangely, this was not enough in my case. I had to add ModelState["{key}"].ValidationState = ModelValidationState.Valid;Truthful
I would assume that you already know what fields are in that model. The containskey check is probably not necessary.Puncheon
K
70

This builds off previous answers, but simplifies it a little more:

foreach (var modelValue in ModelState.Values)
{
    modelValue.Errors.Clear();
}
Kershner answered 14/4, 2012 at 21:47 Comment(0)
U
8

I use it sometimes, so I've made an extension method out of it:

public static ModelStateDictionary ClearError(this ModelStateDictionary m, string fieldName)
{
    if (m.ContainsKey(fieldName))
        m[fieldName].Errors.Clear();
    return m;
}

It can be used fluently to clear error for multiple fields.

Unlovely answered 1/6, 2014 at 22:34 Comment(0)
W
7

In general, you don't want to turn off the server-side validation or remove ModelState errors manually. It's doable, but error-prone since it must rely on strings as keys. I upvoted the answer on how to remove the keys, because it is correct and useful, but I recommend against designing yourself into a case where you must strongly consider it.

In your case, you have multiple submit buttons for the same form, but you really aren't submitting the form when you upload the image. To prevent the client-side validation, you can use the "cancel" class as you've already indicated, but I also recommend having the 2nd submit button in a different form, in which case it causes no validation on your main form.

There is a second advantage to using the different form: you can send it to a different ActionResult method which would just handle the logic of uploading the image. This different method would simply not bother to check the "IsValid" property of the model state: it only cares if there is information in the image, and that can be checked separately. (Even if you use the same ActionResult method, you can funnel the logic so that you don't rely on the IsValid property of the model state.)

If you must clear the errors from the model state, and it makes sense to clear all of them, try this:

foreach (var key in ModelState.Keys)
{
    ModelState[key].Errors.Clear();
}

This keeps you from depending on getting the key names correct, but preserves the values should any values (valid or invalid) already exist in the model.

One last thing to check for in these cases is whether you have values that are only sometimes in the view, which will not cause client-side validation (they're not in the view), but do result in server-side validation issues. In this case, it's best to use @Html.HiddenFor(model => model.PropertyName, if you can, assuming the value has already been set, it just isn't visible in this view.

Winchester answered 5/6, 2013 at 17:41 Comment(0)
P
5

use ModelState.Remove("{key}") to remove the error from model , which will reset the ModelState.IsValid to true

ModelState.Remove("{key}");
Phylloquinone answered 6/12, 2018 at 9:5 Comment(0)
F
0
ModelState.ClearValidationState("KeyName");
ModelState.MarkFieldValid("KeyName");
Flatwise answered 24/8, 2022 at 16:40 Comment(0)
L
0

Here's code that loops through all the errors and removes the ones that are NOT in the desired page. I have two pages and I only want to show the errors for the 1st page. (The 2nd page is hidden but will be visible later when page 1 is hidden.) You simply get the errors and loop through and remove the errors that are not in the currently visible page. PageNum is an integer set earlier.

var errors = ModelState.Keys.Where(k => ModelState[k].Errors.Count > 0).Select(k => new { propertyName = k, errorMessage = ModelState[k].Errors[0].ErrorMessage });

bool isError = false;

foreach (var error in errors)
{
    isError = CheckForErrors(error.propertyName, pageNum);
    ModelState.Remove(error.propertyName);
}

private bool CheckForErrors(string propertyName, int page)
{
    var Page1Properties = new Dictionary<string, string>();
    Page1Properties.Add("biz_dbaBusinessName", "biz_dbaBusinessName");

    var Page2Properties = new Dictionary<string, string>();
    Page2Properties.Add("bank_name", "bank_name");

    string result;

    switch (page)
    {
        case 1:
            return (Page1Properties.TryGetValue(propertyName, out result));
            break;
        case 2:
            return (Page2Properties.TryGetValue(propertyName, out result));
            break;
        default:
            break;
    }

    return false;
}
Lao answered 29/11, 2022 at 22:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.