asp.net-mvc modelstate.isvalid - ¿Cómo obtener todos los errores de ASP.Net MVC modelState?




show errors (13)

Útil para pasar una serie de mensajes de error a la Vista, quizás a través de Json:

messageArray = this.ViewData.ModelState.Values.SelectMany(modelState => modelState.Errors, (modelState, error) => error.ErrorMessage).ToArray();

Quiero eliminar todos los mensajes de error de modelState sin conocer los valores clave. Recorriendo para capturar todos los mensajes de error que contiene ModelState.

¿Cómo puedo hacer esto?


Como descubrí que seguí los consejos de las respuestas proporcionadas hasta ahora, puede obtener excepciones sin que se establezcan mensajes de error, por lo que para detectar todos los problemas que realmente necesita para obtener tanto el ErrorMessage como la Excepción.

String messages = String.Join(Environment.NewLine, ModelState.Values.SelectMany(v => v.Errors)
                                                           .Select( v => v.ErrorMessage + " " + v.Exception));

o como método de extensión

public static IEnumerable<String> GetErrors(this ModelStateDictionary modelState)
{
      return modelState.Values.SelectMany(v => v.Errors)
                              .Select( v => v.ErrorMessage + " " + v.Exception).ToList();

}

Por si acaso alguien lo necesita, hice y uso la siguiente clase estática en mis proyectos.

Ejemplo de uso:

if (!ModelState.IsValid)
{
    var errors = ModelState.GetModelErrors();
    return Json(new { errors });
}

Usos:

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using WebGrease.Css.Extensions;

Clase:

public static class ModelStateErrorHandler
{
    /// <summary>
    /// Returns a Key/Value pair with all the errors in the model
    /// according to the data annotation properties.
    /// </summary>
    /// <param name="errDictionary"></param>
    /// <returns>
    /// Key: Name of the property
    /// Value: The error message returned from data annotation
    /// </returns>
    public static Dictionary<string, string> GetModelErrors(this ModelStateDictionary errDictionary)
    {
        var errors = new Dictionary<string, string>();
        errDictionary.Where(k => k.Value.Errors.Count > 0).ForEach(i =>
        {
            var er = string.Join(", ", i.Value.Errors.Select(e => e.ErrorMessage).ToArray());
            errors.Add(i.Key, er);
        });
        return errors;
    }

    public static string StringifyModelErrors(this ModelStateDictionary errDictionary)
    {
        var errorsBuilder = new StringBuilder();
        var errors = errDictionary.GetModelErrors();
        errors.ForEach(key => errorsBuilder.AppendFormat("{0}: {1} -", key.Key,key.Value));
        return errorsBuilder.ToString();
    }
}

Pude hacer esto usando un poco de LINQ,

public static List<string> GetErrorListFromModelState
                                              (ModelStateDictionary modelState)
{
      var query = from state in modelState.Values
                  from error in state.Errors
                  select error.ErrorMessage;

      var errorList = query.ToList();
      return errorList;
}

El método anterior devuelve una lista de errores de validación.

Otras lecturas :

Cómo leer todos los errores de ModelState en ASP.NET MVC


En caso de que alguien quiera devolver el nombre de la propiedad del modelo para vincular el mensaje de error en una vista fuertemente tipada.

List<ErrorResult> Errors = new List<ErrorResult>();
foreach (KeyValuePair<string, ModelState> modelStateDD in ViewData.ModelState)
{
    string key = modelStateDD.Key;
    ModelState modelState = modelStateDD.Value;

    foreach (ModelError error in modelState.Errors)
    {
        ErrorResult er = new ErrorResult();
        er.ErrorMessage = error.ErrorMessage;
        er.Field = key;
        Errors.Add(er);
    }
}

De esta manera, realmente puede vincular el error con el campo que lanzó el error.


Utilizando LINQ :

IEnumerable<ModelError> allErrors = ModelState.Values.SelectMany(v => v.Errors);

Además, ModelState.Values.ErrorMessage puede estar vacío, pero ModelState.Values.Exception.Message puede indicar un error.


Y esto funciona también:

var query = from state in ModelState.Values
    from error in state.Errors
    select error.ErrorMessage;
var errors = query.ToArray(); // ToList() and so on...


Basándose en la versión LINQ, si desea unir todos los mensajes de error en una cadena:

string messages = string.Join("; ", ModelState.Values
                                        .SelectMany(x => x.Errors)
                                        .Select(x => x.ErrorMessage));

La salida de solo los mensajes de error en sí no fue suficiente para mí, pero esto resultó ser el truco.

var modelQuery = (from kvp in ModelState
                  let field = kvp.Key
                  let state = kvp.Value
                  where state.Errors.Count > 0
                  let val = state.Value.AttemptedValue ?? "[NULL]"

                  let errors = string.Join(";", state.Errors.Select(err => err.ErrorMessage))
                  select string.Format("{0}:[{1}] (ERRORS: {2})", field, val, errors));

Trace.WriteLine(string.Join(Environment.NewLine, modelQuery));

En tu implementación faltan clases estáticas, esto debería ser.

if (!ModelState.IsValid)
{
    var errors =  ModelStateErrorHandler.GetModelErrors(this.ModelState);
    return Json(new { errors });
}

más bien

if (!ModelState.IsValid)
{
    var errors = ModelState.GetModelErrors();
    return Json(new { errors });
}

Soy nuevo en ASP.NET MVC. Me enfrenté con el mismo problema, el siguiente es mi trabajo en mi Erorr.vbhtml (funciona si solo necesita registrar el error usando el registro de Elmah)

@ModelType System.Web.Mvc.HandleErrorInfo

    @Code
        ViewData("Title") = "Error"
        Dim item As HandleErrorInfo = CType(Model, HandleErrorInfo)
        //To log error with Elmah
        Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(New Elmah.Error(Model.Exception, HttpContext.Current))
    End Code

<h2>
    Sorry, an error occurred while processing your request.<br />

    @item.ActionName<br />
    @item.ControllerName<br />
    @item.Exception.Message
</h2> 

¡Es sencillo!





asp.net-mvc modelstate