How to figure out which key of ModelState has error
Asked Answered
L

7

23

How do I figure out which of the keys in ModelState that contains an error when ModelState.IsValid is false? Usually I would just hover the mouse thru the ModelState.Values list checking item by item for error count > 0. But now I'm working on a view that has some lists of complex objects, totalling 252 ModelState items(each item of each object of each list has an entry on ModelState.Keys).

So, is there an easier way to point out the error source?

Listlessness answered 8/3, 2013 at 14:19 Comment(0)
E
37

You can check the ViewData.ModelState.Values collection and see what are the Errors.

[Httpost]
public ActionResult Create(User model)
{
   if(ModelState.IsValid)
   {
     //Save and redirect
   }
   else
   {
     foreach (var modelStateVal in ViewData.ModelState.Values)
     {
       foreach (var error in modelStateVal.Errors)
       {               
          var errorMessage = error.ErrorMessage;
          var exception = error.Exception;
          // You may log the errors if you want
       }
     }
   }         
   return View(model);
 }
}

If you really want the Keys(the property name), You can iterate through the ModelState.Keys

foreach (var modelStateKey in ViewData.ModelState.Keys)
{
    var modelStateVal = ViewData.ModelState[modelStateKey];
    foreach (var error in modelStateVal.Errors)
    {
        var key = modelStateKey; 
        var errorMessage = error.ErrorMessage;
        var exception = error.Exception;
        // You may log the errors if you want
    }
}
Emden answered 8/3, 2013 at 14:21 Comment(5)
This helped me find the problem. Wasn't exactly what I was looking for, but solved anyways... thanks!Listlessness
This works, but doesn't answer the question; how to find out which KEY of the ModelState has an error. In this solution, we get the error, but not the key this error belongs to. How do we achieve that?Guillen
@RensdeNobel I updated the answer to include that as well.Emden
The Key seems to include some GUID. Don't forget to sanitize it.Izolaiztaccihuatl
It is baffling to me why the validation error collection is implemented this way where you cannot simply select the errors based on key (or part of the key) e.g. ViewData.ModelState.Values.Where(w => w.Key.StartsWith("something")). I guess they have their reasons.Unforgettable
P
3
ModelState.Values.SelectMany(v => v.Errors);

is considered cleaner.

Pichardo answered 8/7, 2013 at 15:23 Comment(2)
This returns only error messages without keys. Not really what OP is looking for.Izolaiztaccihuatl
ModelState.KeysOdalisque
S
1

where modelState is a ModelStateDictionary object

foreach (var keyModelStatePair in modelState)
    {
        var key = keyModelStatePair.Key;
        var errors = keyModelStatePair.Value.Errors;
        if (errors != null && errors.Count > 0)
        {
            var errorMessages = errors.Select(error =>
            {
                return error.ErrorMessage;
            }).ToArray();

            // do something with your keys and errorMessages here
        }
    }
Sapp answered 24/6, 2022 at 23:6 Comment(0)
D
1

I had the same problem for a long time and finally I found it. In my case, it was the Id field :)

Just place a breakpoint and check your ModelState in runtime and go to this section :

ModelState -> Root -> Children

and you will see all valid and invalid Keys

enter image description here

Dappled answered 24/9, 2022 at 20:25 Comment(1)
I don't have a "Root" element in my case.Grainger
O
1

following method Gives Dictionary Response of errors can Return it In Badrequest Based on th functionality.

        var ErrorDictionary=ModelState
                .Where(x => x.Value.Errors.Count > 0)
                .ToList()
                .ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Errors.Select(x => x.ErrorMessage).ToList());
Odorous answered 6/7, 2023 at 4:26 Comment(1)
You can remove the .List() part.Grainger
B
0

Did some modification to the solution provided by @cblanto7.

    _logger.LogInformation("ModelState is not valid: In yourmodelName/yourActionName.");
    foreach (var keyModelStatePair in ModelState)
    {
        var errors = keyModelStatePair.Value.Errors;
        if (errors != null && errors.Count > 0)
        {
            var key = keyModelStatePair.Key;
            var errorMessageArray = errors.Select(error =>
            {
                return error.ErrorMessage;
            }).ToArray();

            var errorMessages = string.Join(", ", errorMessageArray); 
            _logger.LogInformation($"ModelState is not valid:{key} has {errorMessages}");
            
        }
    }
Benz answered 6/7, 2023 at 1:59 Comment(0)
G
0

Based on @Upender Reddy's answer, I just got this very practical expression to use on the Watch window for debugging:

ModelState.Where(x => x.Value.Errors.Count > 0)

Just notice that ModelState is from type ModelStateDictionary, which implements IDictionary<string, ModelState> interface, so it means one can use LINQ methods on it.

Grainger answered 19/9, 2023 at 8:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.