views:

462

answers:

3

How do you get a list of all ModelState error messages? I found this code to get all the keys: ( http://stackoverflow.com/questions/888521/returning-a-list-of-keys-with-modelstate-errors)

var errorKeys = (from item in ModelState
        where item.Value.Errors.Any() 
        select item.Key).ToList();

But how would I get the error messages as a IList or IQueryable?

I could go:

foreach (var key in errorKeys)
{
    string msg = ModelState[error].Errors[0].ErrorMessage;
    errorList.Add(msg);
}

But thats doing it manually - surely there is a way to do it using LINQ? The .ErrorMessage property is so far down the chain that I don't know how to write the LINQ...

+5  A: 
SLaks
Thats a quick reply :)! Hey that looks good, but what if ModelState[item.Key] has more than 1 error? Errors[0] only works for a single error message
JK
How do you want to combine them?
SLaks
Thanks thats almost it - but its selecting every key even if it has no errors - how can we filter out the keys with no errors?
JK
Add `.Where(kvp => kvp.Value.Errors.Count > 0)`
SLaks
+1  A: 

Here is the full implementation with all the pieces put together:

1st create an extension method:

public static class ModelStateHelper
{
    public static IEnumerable Errors(this ModelStateDictionary modelState)
    {
        if (!modelState.IsValid)
        {
            return modelState.ToDictionary(kvp => kvp.Key,
                kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()).Where(m => m.Value.Count() > 0);
        }
        return null;
    }
}

Then return the errors from the controller action (if any) as json:

            if (!ModelState.IsValid)
            {
                return Json(new { Errors = ModelState.Errors() }, JsonRequestBehavior.AllowGet);
            }

And then finally, show those errors on the clientside (in jquery.validation style, but can be easily changed to any other style)

function DisplayErrors(errors) {
    for (var i = 0; i < errors.length; i++) {
        $("<label for='" + errors[i].Key + "' class='error'></label>").html(errors[i].Value[0]).appendTo($("input#" + errors[i].Key).parent());
    }
}
JK
This looks like an interesting method however the helper class isn't working for me. Is this due to changes perhaps with MVC 2? I'm getting an error that the ToDictionary method doesn't exist on modelState.
Cymen
@Cymen are you forgetting to reference System.Linq? ToDictionary() is a LINQ extension method.
Nathan Taylor
A: 

ToDictionary is an Enumerable extension found in System.Linq packaged in the System.Web.Extensions dll http://msdn.microsoft.com/en-us/library/system.linq.enumerable.todictionary.aspx. Here's what the complete class looks like for me.

using System.Collections;
using System.Web.Mvc;
using System.Linq;

namespace MyNamespace
{
    public static class ModelStateExtensions
    {
        public static IEnumerable Errors(this ModelStateDictionary modelState)
        {
            if (!modelState.IsValid)
            {
                return modelState.ToDictionary(kvp => kvp.Key,
                    kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()).Where(m => m.Value.Count() > 0);
            }
            return null;
        }

    }

}
philrabin