Laden...

(CRUD / .NET Core) HttpContext.Response - ErrorMessage

Erstellt von Froschkoenig84 vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.919 Views
F
Froschkoenig84 Themenstarter:in
63 Beiträge seit 2015
vor 4 Jahren
(CRUD / .NET Core) HttpContext.Response - ErrorMessage

Infos:
:::

#:::

Hallo,

ich habe heute meine aller erste CRUD-API unter .NET Core gebaut und möchte gerne einen Fehler zurückgeben...

// PUT api/users/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] Dictionary<string,object> modFields)
{
    var userProbs = typeof(User).GetProperties().Select(p => p.Name);
    var unknownFields = modFields.Keys.Where(k => !userProbs.Contains(k, StringComparer.OrdinalIgnoreCase));
    if (unknownFields.Count() == 0)
    {
        // _repo.ModUser(id, modUser);
    } 
    else
    {
        HttpContext.Response.StatusCode = 502;
    }
}

Okay, so kann ich also einen StatusCode zurückgeben, aber gibt es hierzu auch einen Status oder eine ErrorMessage? - Will dem Client sagen, dass sein Put-Data nicht unterstützte Felder besitzt und daher nicht verarbeitet wird.

Das muss ja möglich sein, hier auch einen Fehler-Text ausgeben zu können oder?

EDIT: Swagger-PUT-Screenshot:

P
441 Beiträge seit 2014
vor 4 Jahren

Vom Prinzip solltest du eine echte Klasse erstellen und diese aus dem Body lesen lassen.
Ist das Model dann nicht valide wird die MVC Middleware von sich aus 404 (vermute ich) senden, weil keine passende Route gefunden wurde.

Reflection würde ich niemals (manuell) da verwenden, wo es sich vermeiden lässt.

F
Froschkoenig84 Themenstarter:in
63 Beiträge seit 2015
vor 4 Jahren

Na ja, die Reflection sei mal dahingestellt, aber gibt es in .NET Core keine individuelle ErrorMessages mehr?

T
2.219 Beiträge seit 2008
vor 4 Jahren

@Froschkoenig84
Was meinst du den mit individueller ErrorMessage?
Da deine Put Methode keinen Response liefert, kann der Client außer dem HTTP Status Code ja keine Meldung erhalten?

Oder beziehst du dich auf das Verhalten der WebAPI?
Was sollte die Web API dann liefern, wenn diese kein gültiges Model auf die Url Mappen kann?
Da auch das Response Format von dir vorgeben werden kann, müsste für eine generierte ErrorMessages auch bekannt sein welches Antworten Format geliefert werden müsste.
Das gehört aber nicht zu den Aufgaben der WebAPI oder .NET Core an dieser Stelle.

Ein Status Code 404 ist hier an sich schon die sinnvollste Lösung um einen Fehler zu vermitteln.
Du kannst diesen Fall aber durch sauberes Fehlerhandling in deiner API abdecken und dann eine Meldung liefern.

Wir setzten bei uns auch eine WebAPI in einem Projekt als neue API ein.
Dort arbeite ich dann mit einer eigenen Implementierung der Controller/Action Selector um diesen Fall abzufangen und eine eigene Json Fehlermeldung nach unserem Format zu liefern.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.806 Beiträge seit 2008
vor 4 Jahren

Die WebAPI ist ein eigenständiges Microsoft Produkt und nennt sich ASP.NET WebAPI und gibt's in der Version 2.2. Dies ging in die ASP.NET MVC Produkte über.
Du verwendest offenbar einfach nur ASP.NET Core und die MVC Middleware.

Du hast in Deiner Action void als Rückgabe - also keine Rückgabe - definiert.
Dann kannst auch nichts ordentlich zurück geben.

Du solltest IActionResult zurück geben, sodass Du a) ordentlich Werte zurückgeben kannst und b) die Middleware weiß, dass überhaupt eine Rückgabe existiert.
Put sollte ohnehin immer eine idempotente Rückgabe haben - und das geht nicht mit void.

Bitte mach einfach Mal die ersten 10 Minuten das ASP.NET Core Tutorial durch - da ist das alles erklärt.
Zudem bitte, wenn Du schon so künstlerisch die Technologien angibst: Gib doch die richtigen Namen an 😃

PS: 404 sagt nur aus, dass etwas nicht gefunden wurde.
Alle logischen Fehler sind später 500.xx Fehler.

F
Froschkoenig84 Themenstarter:in
63 Beiträge seit 2015
vor 4 Jahren

Wie ihr seht, hatte ich ja die Rückgabe nur testweise auf VOID zrückgesetzt. Daher ist die reguläre/erfolgreiche Rückgabe ja auch auskommentiert. Wobei ich gerade sehe, das sich - wieso auch immer das return weggenommen hab. - Aber egal...

Ich suche nur nach einer Möglichkeit, neben dem StatusCode noch eine zusätzliche ErrorMessage zurückzugeben. Aber ich denke, verstanden zu haben, dass ich die Fehler quasi als klassische Rückgabe definieren müsste, ...

...bei einem invaliden POST wurde diese Ausgabe automatisch generiert, auch wenn mir die Trace-ID noch nicht ganz klar ist. **:::

Notfalls baue ich die Ausgabe händisch nach.
Ich vermute mal
[400 Bad Request] und als ErrorMessage eben die obige Ausgabe mit den aufgelisteten unbekannten Feldern. Ggf. würde sicherlich auch ein 5XX gehen, aber ich finde keinen passenden.
Daher den 400er oder doch den 404er. Wobei die angefragte Ressource ja gefunden wurde, nur dass die übermittelten Felder nicht existieren.

F
Froschkoenig84 Themenstarter:in
63 Beiträge seit 2015
vor 4 Jahren

Sicherlich wäre es nützlich später noch eine Validierungsklasse zu erzeugen. Wie gesagt, ich probiere noch aus. Aber händisch erzeugt wäre es dieser Code... (Sorry wegen des Quick'n'Dirty-JSON-Objekts)

// PUT api/users/5
[HttpPut("{id}")]
public object Put(int id, [FromBody] Dictionary<string,object> modFields)
{
    var userProbs = typeof(User).GetProperties().Select(p => p.Name);
    var unknownFields = modFields.Keys.Where(k => !userProbs.Contains(k, StringComparer.OrdinalIgnoreCase));
    if (unknownFields.Count() == 0)
    {
        //return _repo.ModUser(id, modUser);
        return 1; //just a test-obj
    } 
    else
    {
        var httpStatusCode = 400;
        var fieldsErrJson = unknownFields.Select(f => "\"" + f + "\": [\"[User." + f + "] field is unknown.\"]").ToList();
        var statusJson = "{ \"errors\": { "+String.Join(", ",fieldsErrJson)+" }, \"title\": \"One or more validation errors occurred.\", \"status\": "+httpStatusCode+", \"traceId\": \"0:00000000\" }";
        
        HttpContext.Response.StatusCode = httpStatusCode;
        return JsonConvert.DeserializeObject<object>(statusJson);
    }
}

Und erzeugt...

Falls das irgendwie einfacher geht, immer her damit. 😃

16.806 Beiträge seit 2008
vor 4 Jahren

Warum object? Wieso untypisiert?
Wieso nicht wie beschrieben und in der Doku nachzulesen IActionResult bzw Task<IActionResult>?
Das hat schon alles so seinen Grund....

Für die Swagger Generierung (normalerweise würde man das Swagger vorher erzeugen, nicht in der Runtime: contract based development) verwendet man Attribute.
Siehe auch ein kurzer 2 Min Blick in die Doku.

Die Doku zeigt übrigens auch ein sauberes exception handling durch entsprechende Pipeline Registrierungen.
Muss man alles nicht selbst erfinden.

F
Froschkoenig84 Themenstarter:in
63 Beiträge seit 2015
vor 4 Jahren

Na ja, Swagger mach ich ja nur, ums zu Testen. Postman wird aus irgendeinem Grund geblockt, da ich das SSL-Zertifikat vom IIS-Express nutze. - Mal sehen, wie das am Ende laufen wird.

Aber Danke für den Hinweis, werde ich am Wochenende mal reinschauen. - Wie gesagt, das ist nur ein Dumm, damit ich weiß, wie ich das zukünftig machen müsste. Feinschliff erfolgt später, ich kann eben nicht gleich perfekt anfangen, außerdem lerne ich mit der Erfahrung.

Am Wochenende muss ich mir mal die ASP.NET Core Identity Auth(s) anschauen. Da ich Dapper nutze, ließ sich das Identity Framework (EF) nicht nutzen. - Es gibt zwar ein paar Git-Projekte, die es mit Dapper realisieren, aber unabhängig davon benötige ich eine einfache Lösung für JWT-Tokens, die ich später mit OAuth-2 (sobald der Kunde etwas mehr Budget freigibt) verknüpfen kann. Ist nur ein internes Dashboard (quasi eine Verwaltungsplattform), daher nicht so kritisch, aber man möchte ja auch für spätere Projekte dazulernen. Wer weiß, vielleicht wird das Ding irgendwann mal riesig und sobald Rechnungen über die Plattform generiert werden, muss es auch wirklich ernsthaft sicher sein.

Aber dennoch vielen Dank für eure Unterstützung, ich nehme das wirklich alles sehr ernst.

16.806 Beiträge seit 2008
vor 4 Jahren

In den Postman Settings kann man SSL verification deaktivieren.
Postman fragt dies auch in einem Pop-up beim ersten Mal ab.