[c#] ASP.NET MVC Come convertire gli errori ModelState in json



4 Answers

Ecco la piena implementazione con tutti i pezzi messi insieme:

Per prima cosa crea un metodo di estensione:

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;
    }
}

Quindi chiama il metodo di estensione e restituisci gli errori dall'azione del controller (se presente) come json:

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

E infine, mostra quegli errori sul lato client (nello stile jquery.validation, ma può essere facilmente modificato in qualsiasi altro stile)

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());
    }
}
Question

Come si ottiene un elenco di tutti i messaggi di errore di ModelState? Ho trovato questo codice per ottenere tutte le chiavi: ( Restituzione di un elenco di chiavi con errori ModelState )

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

Ma come potrei ottenere i messaggi di errore come IList o IQueryable?

Potrei andare:

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

Ma questo è farlo manualmente - sicuramente c'è un modo per farlo usando LINQ? La proprietà .ErrorMessage è così giù lungo la catena che non so come scrivere LINQ ...




Ci sono molti modi diversi per fare tutto ciò che funziona. Ecco ora lo faccio ...

if (ModelState.IsValid)
{
    return Json("Success");
}
else
{
    return Json(ModelState.Values.SelectMany(x => x.Errors));
}



Il modo più semplice per farlo è restituire una BadRequest con lo stesso ModelState:

Ad esempio su un PUT :

[HttpPut]
public async Task<IHttpActionResult> UpdateAsync(Update update)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    // perform the update

    return StatusCode(HttpStatusCode.NoContent);
}

Se usiamo annotazioni di dati, ad esempio un numero di cellulare, come questo, nella classe Update :

public class Update {
    [StringLength(22, MinimumLength = 8)]
    [RegularExpression(@"^\d{8}$|^00\d{6,20}$|^\+\d{6,20}$")]
    public string MobileNumber { get; set; }
}

Ciò restituirà quanto segue su una richiesta non valida:

{
  "Message": "The request is invalid.",
  "ModelState": {
    "update.MobileNumber": [
      "The field MobileNumber must match the regular expression '^\\d{8}$|^00\\d{6,20}$|^\\+\\d{6,20}$'.",
      "The field MobileNumber must be a string with a minimum length of 8 and a maximum length of 22."
    ]
  }
}



Variazione con tipo restituito invece di restituire IEnumerable

public static class ModelStateHelper
{
    public static IEnumerable<KeyValuePair<string, string[]>> 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.Any());
        }

        return null;
    }
}



Perché non restituire l'oggetto ModelState originale al client e quindi utilizzare jQuery per leggere i valori. Per me sembra molto più semplice e utilizza la struttura dati comune (.net's ModelState )

per restituire ModelState come Json, basta passarlo al costruttore della classe Json (funziona con QUALSIASI oggetto)

C #:

return Json(ModelState);

js:

        var message = "";
        if (e.response.length > 0) {
            $.each(e.response, function(i, fieldItem) {
                $.each(fieldItem.Value.Errors, function(j, errItem) {
                    message += errItem.ErrorMessage;
                });
                message += "\n";
            });
            alert(message);
        }





Related