2016-08-16 4 views
1

APIのHMACセキュリティを実装しようとしています。私はMultipartFormDataContentのファイルの横にデータ値を投稿しようとするまで、すべてうまく動作します。複数のコンテンツタイプが存在する場合、HttpContentバイトの読み取りがDelegatingHandler内で失敗する

HttpClientDelegatingHandlerは、バイトを読み取る非同期コード行がヒットしたときに自動的に失敗します。ここで

は要求を構築するコードです:

private FileOutputViewModel GetApiOutput(Uri apiResource, string filename, byte[] file, IDictionary<string, string> extraParameters) 
{ 
    FileOutputViewModel result = new FileOutputViewModel(); 

    if (file != null) 
    { 
     using (var content = new MultipartFormDataContent()) 
     { 
      if (extraParameters != null) 
      { 
       foreach (var param in extraParameters) 
       { 
        content.Add(new StringContent(param.Value), param.Key); // <- If I don't have this, everything works fine 
       } 
      } 

      var fileContent = new ByteArrayContent(file); 
      fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") 
      { 
       FileName = filename 
      }; 
      content.Add(fileContent); 

      var response = HttpClient.PostAsync(apiResource.ToString(), content).Result; 

      result.Output = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result); 

      result.Filename = Path.GetFileName(filename); 
     } 
    } 

    return result; 
} 

私はDelegatingHandlerすべてがうまく動作しますが、HMACのセキュリティはそうAPIの最後に拒否された要求のために実装されていない使用しない場合。

ファイルの横にStringContent個のアイテムを使用してデータ値を追加しないと、バイトを読み取る際に問題はありません。しかし、私はファイルと一緒に多くの情報を渡す必要があるので、不完全な要求が残されています。

DelegatingHandlerに失敗したコード行を以下に示す:

private static async Task<byte[]> ComputeHash(HttpContent httpContent) 
{ 
    using (var md5 = MD5.Create()) 
    { 
     byte[] hash = null; 
     if (httpContent != null) 
     { 
      var ms = new MemoryStream(); 
      await httpContent.CopyToAsync(ms); // <- Fails here 
      ms.Seek(0, SeekOrigin.Begin); 

      var content = ms.ToArray(); 
      if (content.Length != 0) 
      { 
       hash = md5.ComputeHash(content); 
      } 
     } 
     return hash; 
    } 
} 

もともとは失敗のラインだった:(前の

var content = await httpContent.ReadAsByteArrayAsync(); 

が、これは自分自身でも、単にファイルで失敗しましたStackoverflow question)。 MemoryStreamを使用することは、一歩前進していたが、私を完全には得られなかった。

どのようにすればこの問題を回避できますか?

答えて

1

これは、System.Net.Http.DelegatingHandler.SendAsyncメソッドの非同期署名が原因であると考えられます。もともとデリゲートオーバーライドされました:すべてが期待どおりに動作し始め

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 

:私は、コードを適応する際

protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 

ので、私はそれを変更することができます。

.NETフレームワークのこの部分でスレッドの問題が発生しているようです。他の回避策を試す必要がある場合は、ここで説明したその他の回避策があります。https://social.msdn.microsoft.com/Forums/vstudio/en-US/55f5571d-fe94-4b68-b1d4-bfb91fd721dd/reading-httpcontent-bytes-fails-inside-delegatinghandler-when-multiple-content-types-present?forum=wcf