2013-07-11 2 views
6

Ich erstelle RESTful-Dienst mit Microsoft ASP.NET Web API.ASP.NET Web API Entfernen von HttpError aus Antworten

Mein Problem betrifft HttpErrors, die die Web-API dem Benutzer zurückgibt, wenn etwas schief geht (z. B. 400 Bad Request oder 404 Not Found).

Das Problem ist, dass ich will nicht serialisiert httperror als Antwort Inhalt erhalten, wie es manchmal zu viel Information liefert, deshalb verletzt es OWASP Sicherheitsregeln, zum Beispiel:

Anfrage:

http://localhost/Service/api/something/555555555555555555555555555555555555555555555555555555555555555555555 

Als Antwort erhalte ich 400 natürlich, aber mit folgenden Inhaltsinformationen:

{ 
"$id": "1", 
"Message": "The request is invalid.", 
"MessageDetail": "The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'MyNamespaceAndMethodHere(Int32)' in 'Service.Controllers.MyController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter." 
} 

So etwas wie dies nur zeigt nicht, dass mein WebServic e basiert auf ASP.NET WebAPI Technologie (was nicht so schlimm ist), sondern auch gibt es einige Informationen über meine Namensräume, Methodennamen, Parameter usw.

Ich versuchte IncludeErrorDetailPolicy in Global.asax zu setzen

Ja, das hat irgendwie gut funktioniert, jetzt enthält das Ergebnis keinen MessageDetail-Abschnitt, aber ich möchte diesen HttpError überhaupt nicht bekommen.

Ich habe auch meine eigenen DelegatingHandler, aber es betrifft auch 400s und 404s, die ich selbst in den Controllern, die ich nicht passieren will.

Meine Frage ist: Gibt es einen bequemen Weg, um serialisierte HttpError von Response Content loszuwerden? Alles, was ich möchte, dass der Benutzer für seine schlechten Anfragen zurückkommt, ist der Antwortcode.

Antwort

1

Wie wäre es mit einem benutzerdefinierten IHttpActionInvoker? Im Grunde müssen Sie nur eine leere HttpResponseMessage senden.

Dies ist ein sehr einfaches Beispiel:

public class MyApiControllerActionInvoker : ApiControllerActionInvoker 
{ 
    public override Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) 
    { 
     var result = base.InvokeActionAsync(actionContext, cancellationToken); 

     if (result.Exception != null) 
     { 
      //Log critical error 
      Debug.WriteLine("unhandled Exception "); 

      return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(HttpStatusCode.InternalServerError)); 
     } 
     else if (result.Result.StatusCode!= HttpStatusCode.OK) 
     { 
      //Log critical error 
      Debug.WriteLine("invalid response status"); 

      return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(result.Result.StatusCode)); 
     } 


     return result; 
    } 
} 

In Global.asax

GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionInvoker), new MyApiControllerActionInvoker()); 

Eine andere wichtige Sache, die Sie tun können, nicht auf Web-Api verwandt, ist eine übermäßige asp.net zu entfernen & IIS HTTP-Header. Here ist eine gute Erklärung.

+0

Nun, ich denke, das wäre gut, aber in meiner Anwendung gebe ich meine eigenen HttpResponseMessages, manchmal als 400 Bad Request, zum Beispiel wenn jemand neue Datensatz in meine Datenbank einfügen will, verwendet er Controller PostNewRecord-Methode. Der Datensatz, den er einfügt, wird durch die Validierung übergeben. Wenn er feststellt, dass einige Felder fehlen, gibt der Controller Bad Request mit meiner eigenen Nachricht zurück, dass einige Felder leer waren. In Ihrer Lösung würde MyApiControllerActionInvoker diese Antwort abfangen und meine Nachricht entfernen, die ich nicht passieren möchte. Ich möchte nur Web-API-generierte Nachrichten entfernen. –

+0

+1 für den verknüpften Artikel. Tolles lesen re: Header –

1

Ich glaube, Ihr Ansatz der Verwendung des Message-Handlers ist korrekt, da der Message-Handler unabhängig von der Komponente in der Web-API-Pipeline, die den Statuscode auf 4xx setzt, den Antworttext löschen kann. Sie möchten jedoch zwischen den explizit festgelegten und den anderen Komponenten unterscheiden. Hier ist mein Vorschlag und ich gebe zu, es ist ein bisschen hacky. Wenn Sie keine andere bessere Lösung erhalten, versuchen Sie es.

In Ihren ApiController Klassen, wenn Sie eine HttpResponseException werfen, setzen Sie ein Flag in Eigenschaften anfordern, so.

Suchen Sie im Nachrichtenhandler nach der Eigenschaft und löschen Sie den Antworttext nicht, wenn die Eigenschaft festgelegt ist.

var response = await base.SendAsync(request, cancellationToken); 

if((int)response.StatusCode > 399 && !request.Properties.Any(p => p.Key == "myException")) 
    response.Content = null; 

return response; 

Sie können dies ein wenig schön verpacken durch eine Erweiterungsmethode zu HttpRequestMessage Zugabe, so dass weder die ApiController noch die Nachrichtenhandler weiß nichts über die hartcodierte Zeichenfolge „MyException“, die ich oben verwenden.

+0

Das würde natürlich funktionieren, aber es ist, wie Sie sagten, eher zu beheben, als langfristige Lösung. –