2014-12-27 1 views
6

Ich habe eine ziemlich einfache Web-API-Anwendung, die derzeit eine Route eingerichtet hat. Wenn der Benutzer versucht, auf eine andere Route zuzugreifen, erhält er 404 zurück, aber der Hauptteil des 404 ist HTML anstelle von JSON (was der Header für die Annahme verlangt). Was ist einfachste (am wenigsten Code/config zu meinem Projekt hinzugefügt) Weg, um IIS auf Anfragen von nicht existierenden Routen mit einer JSON-Fehlerantwort statt einer Webseite zu reagieren?Wie gebe ich Json für 404s und 403s in WebAPI zurück?

Die gleiche Frage gilt für 403s. Wenn ich versuche, zur Wurzel meiner Anwendung zu navigieren, bekomme ich eine 403 zurück, wiederum als Webseite. Ich würde es vorziehen, ein 404 sein, aber die größere Frage ist, wie mache ich alle Antworten aus meiner Anwendung JSON statt nur Antworten auf gültige Routen? Ich erwähne die 403, weil ich nach einer breiteren Lösung suche, als nur eine Catch-All-Route einzurichten, da ich nicht glaube, dass mir das bei der 403 oder einer anderen zufälligen Ausnahme hilft, die außerhalb einer Controller-Aktion auftritt.

Am liebsten möchte ich, dass meine Anwendung den Header akzeptiert. Da meine API derzeit jedoch nur JSON unterstützt, bin ich bereit, mit (vorläufig) immer mit JSON zu reagieren.

Ich verwende WebAPI 2.2 und .NET 4.5.2.

bearbeiten

Dies ist kein Formatierer Problem. Die Formatierer werden korrekt auf erfolgreiche Nachrichten angewendet, wobei der akzeptierende Header in der Anforderung berücksichtigt wird. Dies ist insbesondere ein Problem mit unbehandelten Routen und Webserverfehlern (wie beim Zugriff auf den Webstamm verboten).

bearbeiten 2

Schritte zum Reproduzieren:

  1. Öffnen Sie Visual Studio 2013 Update 4
  2. Neues Projekt
  3. Wählen Sie .NET Framework 4.5.2
  4. Vorlagen wählen > Visual C#> Web> ASP.NET-Webanwendung
  5. Wählen Sie "Leer", lassen Sie alle Ordner und Kernreferenzen unmarkiert.
  6. Klicken Sie mit der rechten Maustaste auf das Projekt> Hinzufügen> Neues Gerüstelement> Web API 2 Controller - Leer
  7. Ändern Sie DefaultController wie unten gezeigt.
  8. Ändern Sie WebApiConfig.cs wie unten gezeigt.
  9. Run/Debug

Was ich erwarte, ist, dass, wenn ich zu http://localhost:<port>/api/do_stuff navigieren Ich sehe Success! in XML- oder JSON je nach akzeptieren Header (was ich tun), und wenn ich zu einer anderen Seite navigieren soll ich sehen Failure! (was ich nicht). Wenn ich stattdessen zu einer anderen Seite navigiere, sehe ich die 404-Antwort von IIS.

DefaultController.cs:

[RoutePrefix("api")] 
public class DefaultController : ApiController 
{ 
    [HttpGet] 
    [Route("do_stuff")] 
    public String DoStuff() 
    { 
     return "Success!"; 
    } 
} 

WebApiConfig.cs:

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     config.MapHttpAttributeRoutes(); 
     config.Filters.Add(new CustomExceptionFilter()); 
    } 

    private class CustomExceptionFilter : ExceptionFilterAttribute 
    { 
     public override void OnException(HttpActionExecutedContext actionExecutedContext) 
     { 
      if (actionExecutedContext.Response.StatusCode == System.Net.HttpStatusCode.NotFound) 
      { 
       actionExecutedContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.NotFound) 
       { 
        Content = new StringContent(@"""Failure!"""), 
       }; 
      } 
     } 
    } 
} 

bearbeitet 3

ich auch einen globalen Exception-Handler und Ausnahme Hinzufügen Logger versucht habe, wie hier gezeigt: http://www.asp.net/web-api/overview/error-handling/web-api-global-error-handling

Weder aufgerufen werden, wenn ich versuche, auf einen ungültiges zu navigieren Im obigen Beispiel route oder zum Site-Root navigieren.

+0

Wenn der Accept-Header ist text/html und nicht application/json dann Rückkehr HTML könnte die richtige Sache irgendwie zu tun. –

+0

Ich glaube nicht, dass diese Antwort hier gilt, weil der Kopf für die Annahme derzeit auf application/json gesetzt ist und ich Text/HTML zurückbekomme. Dies bedeutet, dass meine Formatierer für fehlende Routen und verbotene Anfragen nicht respektiert werden. –

+0

Obwohl ich die von Ihnen erwähnten Schritte überprüfen und zurücksetzen, aber Sie können CustomExceptionFilter eine eigenständige öffentliche Klasse machen, was ist der Punkt, um es zu einer privaten Klasse zu machen, mein Verständnis ist, auch wenn Sie registriert haben, wird es nur für Ausnahmen arbeiten WebAPIConfig und deshalb löst es keine der aufgetretenen Exceptions aus. –

Antwort

-1

Rufen Sie die Funktion unten von der geplanten Catch-All-Route wie eine JsonResult Aktion zurückzukehren unter

public JsonResult Handle404() 
{ 
    return Json(new { error404 = "NOT FOUND", Message = "Additional Message" }); 
} 

die

var result = 
{ 
    "error404": "NOT FOUND", 
    "Message": "Additional Message" 
}; 

alert(result.error404); 
allert(result.Message); 
+1

Eine Catch-all-Route löst die 404s explizit, aber was ist mit all den anderen Ausnahmen, die meine Anwendung auslösen könnte? Ein leicht zu reproduzierendes Beispiel ist das 403, das ich bekomme, wenn ich versuche, auf den Stamm meiner Anwendung zuzugreifen.Andere könnten IIS Konfigurationsfehler, Anwendungskonfigurationsfehler, Anwendung abstürzt, usw. Ich schließe verstehen, dass ich wahrscheinlich nicht IIS JSON bekommen kann wirklich fatale Fehler zurück (wie aus der Erinnerung), aber ich würde JSON Antworten für alles mögen. –

0

erstellen Exception Filter im WebAPI produzieren und wenden Sie es global um jegliche Art von .Net- oder benutzerdefinierten Ausnahmen zu behandeln. Ändern Sie intern in der OnException-Methode die Response-Eigenschaft der Context-Klasse in Json, indem Sie ein Objekt wie Fehler mit Code und Nachricht an Json serialisieren. Überprüfen Sie die folgenden link:

Es folgt eine Implementierung in meinem Code:

// Filter erstellen

public class ViewRExceptionFilterAttribute : ExceptionFilterAttribute 
{ 
public override void OnException(HttpActionExecutedContext context) 
{ 
    context.Response = new HttpResponseMessage 
     { 
      Content = new StringContent(globalHttpContextMessage) 
     }; 
} 
} 

Hier globalHttpContextMessage mit dem folgenden Code:

globalHttpContextMessage = JsonConvert.SerializeObject(exceptionMessageUI, Formatting.Indented); 

Ausnahmemeldung UI-Schema ist wie folgt:

[JsonObject] 
    public class ExceptionMessageUI 
    { 
     /// <summary> 
     /// 
     /// </summary> 
     public int ErrorCode { get; set; } 

     /// <summary> 
     /// 
     /// </summary> 
     public string ErrorMessage { get; set; } 
    } 

// Filter Registrierung

public static class WebApiConfig 
    { 
     public static void Register(HttpConfiguration config) 
     { 
      config.Filters.Add(new ViewRExceptionFilterAttribute()); 
     } 
    } 
+0

Ich habe eine Ausnahme-Filter und setzen Sie einen Haltepunkt in OnException und es scheint nicht immer getroffen werden. Ich bin derzeit in IISExpress für das Debuggen ausgeführt wird, habe ich noch nicht in voller IIS versucht, obwohl im Idealfall würde ich eine solche Lösung, die unabhängig von Hosting-Methode funktioniert. –

+0

Es scheint nicht getroffen zu, wenn IIS entweder gehostet. –

+0

Das seltsame ist, funktioniert es für mich immer und alle Hosting-Szenario Visual Studio-Entwicklungs Web-Server inlcuding, ich nur Grund denken kann, ist ein Filter nicht auf einen Typ eingetragen oder angemeldet abzufangen und die Context Response zu ändern. Bitte überprüfen oder listen Sie die Schritte auf, die Sie bisher unternommen haben. Normalerweise funktioniert die Registrierung in Globa.asax.cs möglicherweise nicht in der neuesten Version. Ich hoffe, dass Sie die Details in dem oberen Link eingefügt bewertet haben: http://www.asp.net/web-api/overview/error-handling/exception-handling –

Verwandte Themen