2016-07-18 5 views
3

У меня есть класс промежуточного ПО OWIN, чтобы выполнить некоторую аутентификацию на основе некоторых пользовательских токенов. Все работает нормально. Однако я хотел бы вернуть полезный ответ об ошибке клиенту. Мое рассуждение состоит в том, что если клиент попросил ответ «application/json», и они ожидают объект сериализации, то это то, что они должны получить, даже если это код состояния 401.Возврат исключений из промежуточного ПО OWIN

Вот раздел Invoke моего промежуточного слоя:

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)); 
    } 

Это все работает отлично, однако:

  • является ли это 'правильный' путь?
  • , что если клиент запрашивает «приложения/XML», который, очевидно, Web API вполне способен поддерживать

Есть ли лучший способ вернуть пользовательский объект ответа («Результат» в моем случае), что сериализуется так, как ожидал клиент?

+0

Этот ответ может помочь вам: http://stackoverflow.com/questions/30918649/unhandled-exception-global-handler-for -owin-katana –

+0

Выглядит как полезный трюк, но я до сих пор не вижу, как использовать IOwinContext для автоматической сериализации объекта ответа (без ручной сериализации с JsonConvert и т. д.). Контроллерам просто нужно вернуть объект, который структура будет сериализована для json или xml. Почему это не может быть промежуточным? – Paul

+0

Я считаю, вы должны сериализовать его самостоятельно, поскольку промежуточное ПО owin выходит за рамки webapi. –

ответ

2

Ну это, кажется, работает, используя дополнительный OwinMiddleware вставляется первая:

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(); 
    } 
Смежные вопросы