ASP.NET MVC Hoe om te zetten ModelState fouten te json

Hoe krijg je een lijst van alle ModelState foutmeldingen? Ik vond deze code om alle sleutels:
( Het retourneren van een lijst van toetsen met ModelState fouten)

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

Maar hoe zou ik de foutmeldingen als een IList of IQueryable?

Ik kon gaan:

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

Maar dat is het handmatig te doen – er is toch een manier om dit te doen met behulp van LINQ? Het .ErrorMessage eigendom is zo ver naar beneden in de keten die ik weet niet hoe het te schrijven, LINQ…

InformationsquelleAutor JK. | 2010-05-16

 

13 Replies
  1. 183

    U kunt iets u wilt in de select clausule:

    var errorList = (from item in ModelState
            where item.Value.Errors.Any() 
            select item.Value.Errors[0].ErrorMessage).ToList();

    BEWERKEN: U kunt het uittreksel van meerdere fouten in afzonderlijke items in de lijst door het toevoegen van een from clausule, zoals deze:

    var errorList = (from item in ModelState.Values
            from error in item.Errors
            select error.ErrorMessage).ToList();

    Of:

    var errorList = ModelState.Values.SelectMany(m => m.Errors)
                                     .Select(e => e.ErrorMessage)
                                     .ToList();

    2nd BEWERKEN:
    U bent op zoek naar een Dictionary<string, string[]>:

    var errorList = ModelState.ToDictionary(
        kvp => kvp.Key,
        kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()
    );
    • Dat is een snelle reactie :)! Hey dat ziet er goed uit, maar wat als ModelState[item.Toets] heeft meer dan 1 fout? Fouten[0] werkt alleen voor een enkele fout bericht
    • Hoe wil je ze combineren?
    • Bedankt dat bijna – maar het selecteren van elke toets, zelfs als het geen-fouten – hoe kunnen we filteren de toetsen zonder fouten?
    • Toevoegen .Where(kvp => kvp.Value.Errors.Count > 0)
    • in uw Waar moet u gebruik maken van Een in plaats van Rekenen>0 .Where(kvp => kvp.Value.Errors.Any())
    • Om dezelfde uitvoer als van Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState); moet u gebruik maken van var errorList = modelState.Where(elem => elem.Value.Errors.Any()) .ToDictionary( kvp => kvp.Key, kvp => kvp.Value.Errors.Select(e => string.IsNullOrEmpty(e.ErrorMessage) ? e.Exception.Message : e.ErrorMessage).ToArray()); Anders kun je het niet hebben ExceptionMessages

  2. 73

    Hier is de volledige uitvoering ervan, met alle stukken samen:

    Voor het eerst een 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.Any());
            }
            return null;
        }
    }

    Bel dan met de extensie methode en de terugkeer van de fouten van de controller actie (indien van toepassing) als json:

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

    En dan eindelijk, toon die fouten op de clientside (in jquery.validatie stijl, maar kan eenvoudig worden gewijzigd in een andere stijl)

    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());
        }
    }
    • Dit lijkt een interessante methode is echter de helper klasse werkt niet voor mij. Is dit het gevolg van de veranderingen misschien met MVC 2? Ik krijg een foutmelding dat de ToDictionary methode bestaat niet op modelState.
    • bent u vergeten op te referentiesysteem.Linq? ToDictionary() is een LINQ extension method.
    • inderdaad — ik vergat terug te komen en bij te werken.
    • Afhankelijk van uw voorkeuren .Where(m => m.Value.Count() > 0) kan ook geschreven worden als .Where(m => m.Value.Any()).
    • Dit kan worden gebruikt op dezelfde manier als de ModelState.ToDataSourceResult() van Kendo.Mvc om terug te keren fouten op het net en foutmeldingen geven bij het bewerken.
  3. 22

    Ik graag gebruik Hashtable hier, dus dat krijg ik JSON object met eigenschappen als sleutels en fouten als waarde in de vorm van een string-array.

    var errors = new Hashtable();
    foreach (var pair in ModelState)
    {
        if (pair.Value.Errors.Count > 0)
        {
            errors[pair.Key] = pair.Value.Errors.Select(error => error.ErrorMessage).ToList();
        }
    }
    return Json(new { success = false, errors });

    Op deze manier krijg je volgende antwoord:

    {
       "success":false,
       "errors":{
          "Phone":[
             "The Phone field is required."
          ]
       }
    }
    • Dit is heel goed antwoord.
  4. 7

    Er zijn veel verschillende manieren om dit te doen dat al het werk. Hier is het nu doe ik het…

    if (ModelState.IsValid)
    {
        return Json("Success");
    }
    else
    {
        return Json(ModelState.Values.SelectMany(x => x.Errors));
    }
    • U kunt ook terugkeren BadRequest(ModelState) en het zal serialiaze in JSON voor u.
  5. 5

    @JK het heeft me veel geholpen, maar waarom niet:

     public class ErrorDetail {
    
            public string fieldName = "";
            public string[] messageList = null;
     }

            if (!modelState.IsValid)
            {
                var errorListAux = (from m in modelState 
                         where m.Value.Errors.Count() > 0 
                         select
                            new ErrorDetail
                            { 
                                    fieldName = m.Key, 
                                    errorList = (from msg in m.Value.Errors 
                                                 select msg.ErrorMessage).ToArray() 
                            })
                         .AsEnumerable()
                         .ToDictionary(v => v.fieldName, v => v);
                return errorListAux;
            }
  6. 4

    De eenvoudigste manier om dit te doen is net terug van een BadRequest met de ModelState zelf:

    Bijvoorbeeld op een PUT:

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

    Als we de gegevens gebruiken annotaties op bijvoorbeeld een mobiel nummer, zoals deze, in de Update klasse:

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

    Dit zal de terugkeer van de volgende op een ongeldige aanvraag:

    {
      "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."
        ]
      }
    }
    • BadRequest is WebAPI, specifieke en op deze vraag is over MVC.
  7. 3

    Een kijkje nemen in het Systeem.Web.Http.De resultaten.OkNegotiatedContentResult.

    Het zet wat u gooien in het JSON.

    Dus ik deed dit

    var errorList = ModelState.ToDictionary(kvp => kvp.Key.Replace("model.", ""), kvp => kvp.Value.Errors[0].ErrorMessage);
    
    return Ok(errorList);

    Dit resulteerde in:

    {
      "Email":"The Email field is not a valid e-mail address."
    }

    Ik ben nog te controleren wat er gebeurt wanneer er meer dan één fout voor elk veld, maar de punt is de OkNegoriatedContentResult is briljant!

    Kreeg de linq/lambda idee van @SLaks

  8. 3

    Eenvoudige manier bereiken door het gebruik van de ingebouwde functionaliteit

    [HttpPost]
    public IActionResult Post([FromBody]CreateDoctorInput createDoctorInput) {
        if (!ModelState.IsValid) {
            return BadRequest(ModelState);
        }
    
        //do something
    }

    JSON resultaat zal worden

  9. 2

    ToDictionary is een Aftelbaar uitbreiding gevonden in het Systeem.Linq verpakt in het Systeem.Web.Extensies dll http://msdn.microsoft.com/en-us/library/system.linq.enumerable.todictionary.aspx. Hier is wat de complete klasse ziet er voor mij is.

    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;
            }
    
        }
    
    }
  10. 2

    Waarom niet terug in de oorspronkelijke ModelState object aan de opdrachtgever, en vervolgens gebruik van jQuery voor het lezen van de waarden. Mij lijkt het veel eenvoudiger is, en maakt gebruik van de gemeenschappelijke gegevens van structuur.net ModelState)

    om terug te keren de ModelState als Json, gewoon doorgeven aan de Json-class constructor (werkt met EEN object)

    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);
            }
  11. 1

    Variatie met return-type in plaats van het retourneren 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;
        }
    }
  12. 0

    Ik heb gemaakt en uitbreiding die wordt tekenreeks geretourneerd met seperator “” (u kunt gebruik maken van uw eigen):

       public static string GetFullErrorMessage(this ModelStateDictionary modelState) {
            var messages = new List<string>();
    
            foreach (var entry in modelState) {
                foreach (var error in entry.Value.Errors)
                    messages.Add(error.ErrorMessage);
            }
    
            return String.Join(" ", messages);
        }
  13. -1
      List<ErrorList> Errors = new List<ErrorList>(); 
    
    
            //test errors.
            var modelStateErrors = this.ModelState.Keys.SelectMany(key => this.ModelState[key].Errors);
    
            foreach (var x in modelStateErrors)
            {
                var errorInfo = new ErrorList()
                {
                    ErrorMessage = x.ErrorMessage
                };
                Errors.Add(errorInfo);
    
            }

    als u gebruik jsonresult dan terug

    return Json(Errors);

    of u kunt gewoon de terugkeer van de modelStateErrors, ik heb niet geprobeerd het. Wat ik deed is het toewijzen van de Fouten collectie naar mijn ViewModel en dan loop het..In dit geval kan ik terug mijn Fouten via json. Ik heb een class/model, ik wilde naar de bron/de sleutel, maar ik ben nog steeds bezig om het te achterhalen.

        public class ErrorList
    {
        public string ErrorMessage;
    }

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *