Fehlermeldung erhalten, wenn ModelState.IsValid fehlschlägt?


74

Ich habe diese Funktion in meinem Controller.

[HttpPost]
public ActionResult Edit(EmployeesViewModel viewModel)
{
    Employee employee = GetEmployee(viewModel.EmployeeId);
    TryUpdateModel(employee);

    if (ModelState.IsValid)
    {
        SaveEmployee(employee);
        TempData["message"] = "Employee has been saved.";
        return RedirectToAction("Details", new { id = employee.EmployeeID });
    }

    return View(viewModel); // validation error, so redisplay same view
}

Es schlägt ModelState.IsValidimmer wieder fehl , gibt immer wieder false zurück und zeigt die Ansicht erneut an. Aber ich habe keine Ahnung, was der Fehler ist.

Gibt es eine Möglichkeit, den Fehler abzurufen und dem Benutzer erneut anzuzeigen?


Antworten:


36

Sie können dies in Ihrer Ansicht tun, ohne etwas Besonderes in Ihrer Aktion zu tun, indem Sie Html.ValidationSummary () verwenden , um alle Fehlermeldungen anzuzeigen , oder Html.ValidationMessageFor () , um eine Meldung für eine bestimmte Eigenschaft des Modells anzuzeigen .

Wenn Sie die Fehler weiterhin in Ihrer Aktion oder Ihrem Controller anzeigen müssen , lesen Sie die ModelState.Errors- Eigenschaft


11
Es gibt keine ModelState.Errors-Eigenschaft?!
Niico

@niico Ich denke, er meint die Eigenschaft vom Typ "ModelState", während die Controller.ModelState-Eigenschaft vom Typ ModelStateDictionary ist.
devlord

3
@niico ModelState.Errors existiert nur für MVC, nicht für WebAPI
Stuzor

143

Versuche dies

if (ModelState.IsValid)
{
    //go on as normal
}
else
{
    var errors = ModelState.Select(x => x.Value.Errors)
                           .Where(y=>y.Count>0)
                           .ToList();
}

Fehler ist eine Liste aller Fehler.

Wenn Sie dem Benutzer die Fehler anzeigen möchten, müssen Sie das Modell nur in die Ansicht zurücksetzen. Wenn Sie die Razor- @Html.ValidationFor()Ausdrücke nicht entfernt haben , wird es angezeigt .

if (ModelState.IsValid)
{
    //go on as normal
}
else
{
    return View(model);
}

Die Ansicht zeigt alle Validierungsfehler neben jedem Feld und / oder in der ValidationSummary an, falls vorhanden.


83

Wenn Sie eine einzelne Fehlermeldung generieren möchten, die die ModelStateFehlermeldungen enthält , können Sie SelectManydie Fehler in einer einzigen Liste zusammenfassen:

if (!ModelState.IsValid)
{
    var message = string.Join(" | ", ModelState.Values
        .SelectMany(v => v.Errors)
        .Select(e => e.ErrorMessage));
    return new HttpStatusCodeResult(HttpStatusCode.BadRequest, message);
}

9
Manchmal wird das ErrorMessagenicht bereitgestellt, z. B. wenn kein erforderliches DateTimeFeld festgelegt ist. Suchen Sie in diesem Fall nach der Ausnahmemeldung, z e.Exception.Message.
WhatIsHeDoing

Manchmal ist das auch nicht vorgesehen! Ich habe eine ModelStatemit 5 Fehlern, jede mit einer Null Exceptionund einer leeren Zeichenfolge für die, ErrorMessagewährend andere Einträge auf der ModelStateeinfach keine Errorsmit ihnen verknüpft haben.
Matt Arnold

6

Wenn der Modalstatus nicht gültig ist und der Fehler nicht auf dem Bildschirm angezeigt wird, weil sich Ihr Steuerelement im reduzierten Akkordeon befindet, können Sie den HttpStatusCode zurückgeben, sodass die tatsächliche Fehlermeldung angezeigt wird, wenn Sie F12 ausführen. Sie können diesen Fehler auch im ELMAH-Fehlerprotokoll protokollieren. Unten ist der Code

if (!ModelState.IsValid)
{
              var message = string.Join(" | ", ModelState.Values
                                            .SelectMany(v => v.Errors)
                                            .Select(e => e.ErrorMessage));

                //Log This exception to ELMAH:
                Exception exception = new Exception(message.ToString());
                Elmah.ErrorSignal.FromCurrentContext().Raise(exception);

                //Return Status Code:
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, message);
}

Beachten Sie jedoch, dass dieser Code alle Validierungsfehler protokolliert. Dies sollte also nur verwendet werden, wenn eine solche Situation auftritt, in der Sie die Fehler nicht auf dem Bildschirm sehen können.


Wäre es möglich, Name / Nachricht-Paare zu erhalten, damit wir wissen, in welchem ​​Feld der Fehler aufgetreten ist?
Matt

4

Wenn jemand für WebApi (nicht MVC) hier ist, geben Sie einfach das ModelStateObjekt zurück:

return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);


2
ModelState.Values.SelectMany(v => v.Errors).ToList().ForEach(x => _logger.Error($"{x.ErrorMessage}\n"));

1

Ok Check and Add to Watch:

  1. Machen Sie einen Haltepunkt an Ihrer ModelState-Zeile in Ihrem Code
  2. Fügen Sie Ihren Modellstatus Ihrer Uhr hinzu
  3. Erweitern Sie ModelState "Werte"
  4. Erweitern Sie Werte "Ergebnisansicht"

Jetzt sehen Sie eine Liste aller SubKey mit ihrem Validierungsstatus am Ende des Werts.

Suchen Sie also nach dem ungültigen Wert .


Nur so funktioniert es für mich, vielen Dank!
Trần Hữu Hiền

1

Es ist eine Beispielerweiterung

public class GetModelErrors
{
    //Usage return Json to View :
    //return Json(new { state = false, message = new GetModelErrors(ModelState).MessagesWithKeys() });
    public class KeyMessages
    {
        public string Key { get; set; }
        public string Message { get; set; }
    }
    private readonly ModelStateDictionary _entry;
    public GetModelErrors(ModelStateDictionary entry)
    {
        _entry = entry;
    }

    public int Count()
    {
        return _entry.ErrorCount;
    }
    public string Exceptions(string sp = "\n")
    {
        return string.Join(sp, _entry.Values
            .SelectMany(v => v.Errors)
            .Select(e => e.Exception));
    }
    public string Messages(string sp = "\n")
    {
        string msg = string.Empty;
        foreach (var item in _entry)
        {
            if (item.Value.ValidationState == ModelValidationState.Invalid)
            {
                msg += string.Join(sp, string.Join(",", item.Value.Errors.Select(i => i.ErrorMessage)));
            }
        }
        return msg;
    }

    public List<KeyMessages> MessagesWithKeys(string sp = "<p> ● ")
    {
        List<KeyMessages> list = new List<KeyMessages>();
        foreach (var item in _entry)
        {
            if (item.Value.ValidationState == ModelValidationState.Invalid)
            {
                list.Add(new KeyMessages
                {
                    Key = item.Key,
                    Message = string.Join(null, item.Value.Errors.Select(i => sp + i.ErrorMessage))
                });
            }
        }
        return list;
    }
}

0

Ich habe keine Ahnung, ob dies Ihr Problem ist, aber wenn Sie einen Benutzer hinzufügen und dann den Namen Ihrer Anwendung ändern, bleibt dieser Benutzer (natürlich) in der Datenbank, ist aber ungültig (was korrektes Verhalten ist). Für diese Art von Fehler wird jedoch kein Fehler hinzugefügt. Die Fehlerliste ist leer, aber ModelState.IsValid gibt für die Anmeldung false zurück.


0

Versuchen

ModelState.Values.First().Errors[0].ErrorMessage

Dies führt nur zum ersten Fehler der ersten Felder. Versuchen Sie, die Antwort von @johnnyHK oben zu lesen.
Janne Harju

0
publicIHttpActionResultPost(Productproduct) {  
    if (ModelState.IsValid) {  
        //Dosomethingwiththeproduct(notshown).  
        returnOk();  
    } else {  
        returnBadRequest();  
    }  
}

ODER

public HttpResponseMessage Post(Product product)
        {
            if (ModelState.IsValid)
            {
                // Do something with the product (not shown).

                return new HttpResponseMessage(HttpStatusCode.OK);
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }
        }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.