2016-10-30 4 views
0

私はHttpResponseMessageメッセージからHttpErrorを引き出しようとしています。 Apiが例外をスローすると、HttpErrorとしてシリアル化されますが、404などのエラーはこの形式にはなりません。例外を使用せずにHttpResponseMessageからHttpErrorの結果を読み取る

私はHttpErrorを逆シリアル化しないとスローされた例外にキャッチして、このコードでこのバグを修正できました。

問題は現在、例外駆動型の開発を使用しています。

Idealy私はこのようなものが欲しいです。

var httpError = await response.Content.TryReadAsAsync<HttpError>(formatters); 
if (httpError == null) 
{ 
    // Definetly not an HttpError and no exception thrown 
} 

確かに、HttpContentのコンテンツの種類を伝える簡単な方法でなければなりませんか?

public static async Task<ApiResponseMessage<T>> GetApiResponseAsync<T>(this HttpResponseMessage response, IEnumerable<MediaTypeFormatter> formatters) where T : class 
     {  
      if (!response.IsSuccessStatusCode) 
      { 
       HttpError httpError; 

       // Exception driven programming 
       try 
       { 
        // Could use string? 
        var contentString = response.Content.ReadAsStringAsync(); 

        // This doesn't work. Throws exception if not correct type 
        var contentObject = await response.Content.ReadAsAsync<object>(); 
        var alwaysNull = contentObject as HttpError; 

        httpError = await response.Content.ReadAsAsync<HttpError>(formatters); 
       } 
       catch (Exception) 
       { 
        httpError = null; 
       } 

       return new ApiResponseMessage<T> 
       { 
        IsSuccess = false, 
        HttpError = httpError, 
        Response = response 
       }; 
      } 
      return new ApiResponseMessage<T> 
      { 
       IsSuccess = true, 
       Result = await response.Content.ReadAsAsync<T>(formatters), 
       Response = response 
      }; 
     } 

答えて

0

もちろん、驚くほど簡単です。

var message = new HttpResponseMessage(); 
HttpError httpError; 
message.TryGetContentValue(out httpError); 

if (httpError != null) 
{ 
    // Do stuff 
} 

編集:コンテンツタイプがタイプたObjectResultではなかったよう

これは私の問題を解決しませんでした。私は、TryGetContentValueがHttpContent.ReadAsAsyncと同じ方法で動作することを期待していました。

ReadAsAsyncのソースコードを掘り下げた後、私は実用的なソリューションを作成しました。

public class ReadAsyncResult<T> 
     { 
      public ReadAsyncResult() 
      { 
      } 

      public ReadAsyncResult(T result) 
      { 
       Result = result; 
       IsSuccess = result != null; 
      } 

      public T Result { get; set; } 
      public bool IsSuccess { get; set; } 
     } 

     public static async Task<ReadAsyncResult<T>> TryReadAsAsync<T>(this HttpContent content) 
     { 
      return await TryReadAsAsync<T>(content, CancellationToken.None); 
     } 

     public static async Task<ReadAsyncResult<T>> TryReadAsAsync<T>(this HttpContent content, CancellationToken cancellationToken) 
     { 
      if (content == null) 
       return new ReadAsyncResult<T>(); 

      var type = typeof(T); 

      var objectContent = content as ObjectContent; 

      if (objectContent?.Value != null && type.IsInstanceOfType(objectContent.Value)) 
      { 
       return new ReadAsyncResult<T>((T)objectContent.Value); 
      } 

      var mediaType = content.Headers.ContentType; 
      var reader = new MediaTypeFormatterCollection(new MediaTypeFormatterCollection()).FindReader(type, mediaType); 

      if (reader == null) return new ReadAsyncResult<T>(); 

      var value = await ReadAsAsyncCore<T>(content, type, reader, cancellationToken); 
      return new ReadAsyncResult<T>(value); 
     } 

     private static async Task<T> ReadAsAsyncCore<T>(HttpContent content, Type type, MediaTypeFormatter formatter, CancellationToken cancellationToken) 
     { 
      cancellationToken.ThrowIfCancellationRequested(); 

      var stream = await content.ReadAsStreamAsync(); 
      var result = await formatter.ReadFromStreamAsync(type, stream, content, null, cancellationToken); 

      return (T) result; 
     } 
関連する問題