2016-07-18 15 views
3

Ich habe eine OWIN-Middleware-Klasse, um eine Authentifizierung basierend auf einigen benutzerdefinierten Tokens durchzuführen. Alles funktioniert gut. Ich möchte jedoch eine nützliche Fehlerantwort an den Client zurückgeben. Mein Argument ist, dass, wenn der Client nach einer "application/json" -Antwort fragt und sie ein serialisiertes Objekt erwartet, dann sollten sie das bekommen, selbst wenn es ein 401-Statuscode ist.Ausnahmen von OWIN-Middleware zurückgeben

Hier ist der Invoke Abschnitt meiner Middleware:

public override async Task Invoke(IOwinContext context) 
    { 
     try 
     { 
      this.DoAuthorization(context); 
      await this.Next.Invoke(context); 
     } 
     catch (UnauthorizedAccessException ex) 
     { 
      this.GenerateErrorResult(context, HttpStatusCode.Unauthorized, this.ExceptionToString(ex)); 
     } 
     catch (Exception ex) 
     { 
      this.GenerateErrorResult(context, HttpStatusCode.InternalServerError, this.ExceptionToString(ex)); 
     } 
    } 

    private void GenerateErrorResult(IOwinContext context, HttpStatusCode code, string errorMessage) 
    { 
     var result = new Result { Status = Result.EStatus.Error, ErrorText = errorMessage }; 

     context.Response.StatusCode = (int)code; 
     context.Response.ContentType = "application/json"; 
     context.Response.Write(JsonConvert.SerializeObject(result)); 
    } 

Das alles funktioniert gut, aber:

  • ist dies die 'richtige' Art und Weise?
  • was ist, wenn der Kunde für ‚application/xml‘ fragt, was offensichtlich Web-API ganz unterstützt

eine bessere Möglichkeit, ein benutzerdefiniertes Antwortobjekt zurückzukehren (‚Ergebnis‘ in meinem Fall) Gibt es fähig ist, dass wird serialisiert, wie der Client es erwarten würde?

+0

Diese Antwort könnte Ihnen helfen: http://stackoverflow.com/questions/30918649/unhandled-exception-global-handler-for -owin-katana –

+0

Sieht wie ein nützlicher Trick aus, aber ich sehe immer noch nicht, wie man mit IOwinContext ein Antwortobjekt automatisch serialisieren kann (ohne manuelle Serialisierung mit JsonConvert usw.). Die Controller müssen nur ein Objekt zurückgeben, das das Framework nach json oder xml serialisiert. Warum kann die Middleware das nicht tun? – Paul

+0

Ich glaube, dass Sie es selbst serialisieren müssen, da owin Middleware aus Webapi-Bereich ist. –

Antwort

2

Gut, das zu funktionieren scheint, wird eine zusätzliche OwinMiddleware mit eingefügt zuerst:

public override async Task Invoke(IOwinContext context) 
    { 
     try 
     { 
      await Next.Invoke(context); 
     } 
     catch (UnauthorizedAccessException ex) 
     { 
      var result = new Result { Status = Result.EStatus.Error, ErrorText = ExceptionToString(ex) }; 

      this.ReturnFormattedResult(result, HttpStatusCode.Unauthorized, context); 
     } 
     catch (Exception ex) 
     { 
      var result = new Result { Status = Result.EStatus.Error, ErrorText = ExceptionToString(ex) }; 

      this.ReturnFormattedResult(result, HttpStatusCode.InternalServerError, context); 
     } 
    } 

    private void ReturnFormattedResult(Result result, HttpStatusCode code, IOwinContext context) 
    { 
     // what should our response be? 
     var mediaType = context.Request.MediaType ?? context.Request.ContentType; 

     // use the accept header (unless it is empty or '*/*' in which case use the content-type 
     if (!string.IsNullOrEmpty(context.Request.Accept) && !context.Request.Accept.Contains("*/*")) 
     { 
      mediaType = context.Request.Accept; 
     } 

     // find a formatter for this media type, if no match then use the first one 
     var formatter = this.config.Formatters.FindWriter(typeof(Result), new MediaTypeHeaderValue(mediaType)); 
     if (formatter == null) 
     { 
      formatter = this.config.Formatters.First(); 
      mediaType = formatter.SupportedMediaTypes.First().MediaType; 
     } 

     context.Response.StatusCode = (int)code; 
     context.Response.ContentType = mediaType; 
     formatter.WriteToStreamAsync(typeof(Result), result, context.Response.Body, null, null).Wait(); 
    } 
Verwandte Themen