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?

Steven
quelle
Es wurde vor stackoverflow.com/questions/1352948/…
Hamzeh.Ebrahimi

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

Daniel Schaffer
quelle
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.

Kapitän Kenpachi
quelle
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);
}
JohnnyHK
quelle
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.

Sachin T Sawant
quelle
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);

codeMonkey
quelle
2
ModelState.Values.SelectMany(v => v.Errors).ToList().ForEach(x => _logger.Error($"{x.ErrorMessage}\n"));
user781861
quelle
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 .

Mostafa Basha
quelle
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;
    }
}
OMANSAK
quelle
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.

user1056921
quelle
0

Versuchen

ModelState.Values.First().Errors[0].ErrorMessage
Delmirio Segura
quelle
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);
            }
        }
San Jaisy
quelle