2016-07-24 9 views
10

私は、次のDTOにHttpContentを変換しています:HttpContentヘッダ一貫性のない列挙

public class ContentDto 
{ 
    public string ContentType {get; set;} 
    public string Headers {get; set; } 
    public object Data { get; set; } 

    public ContentDto(HttpContent content) 
    { 
      Headers = content.Headers.Flatten(); 
      // rest of the setup 
    } 
} 

、その上にいくつかのユニットテストを実行しています:

[Fact] 
public void CanBuild() 
{ 
    var content = new StringContent("some json", Enconding.UTF8, "application/json"); 
    var dto = new ContentDto(content); 

    var contentHeaders = content.Headers.Flatten(); 

    Assert.Equal(contentHeaders, dto.Headers); 
} 

そしてContent-Lengthヘッダーがされていないので、そのテストが失敗しました私のdtoに捕らえられた。ただし、私が行う場合:

[Fact] 
public void CanBuild() 
{ 
    var content = new StringContent("some json", Enconding.UTF8, "application/json"); 

    var contentHeaders = content.Headers.Flatten(); 

    var dto = new ContentDto(content); 

    Assert.Equal(contentHeaders, dto.Headers); 
} 

テストに合格し、すべてのヘッダーがキャプチャされます。

[Fact] 
public void CanBuild() 
{ 
    var content = new StringContent("some json", Enconding.UTF8, "application/json"); 

    var dto = new ContentDto(content); 

    var contentHeaders = content.Headers.Flatten(); 

    var dto1 = new ContentDto(content); 

    Assert.Equal(contentHeaders, dto.Headers);     
    Assert.Equal(contentHeaders, dto1.Headers); 
} 

、それはContent-Lengthヘッダーを持っていないdtoので、失敗しますが、dto1行います。さらに、私もこれを試してみました。私ならば、どんなにをContent-Lengthヘッダに関するStringContentクラスに関する特別な何かがあったかどうかを確認するために

public static ContentDto FromContent<T>(T content) where T : HttpContent 
{ 
     // same as the constructor 
} 

が、それは何の違いが行われていない:私もこのような工場のようなメソッド内のヘッダを取得しようとしましたコンストラクタ(基本クラスHttpContentを使用)または汎用メソッドFromContent(この場合は実際のStringContentを使用)を使用して、結果は同じでした。

だから私の質問は以下のとおりです。

HttpContent.Headersのその意図された動作ですか?
実際のHttpContentタイプに固有のヘッダがいくつかありますか?
私はここで何が欠けていますか?

注:これはFlatten拡張メソッドのコードです:

public static string Flatten(this HttpHeaders headers) 
{ 
     var data = headers.ToDictionary(h => h.Key, h => string.Join("; ", h.Value)) 
         .Select(kvp => $"{kvp.Key}: {kvp.Value}"); 

     return string.Join(Environment.NewLine, data) 
} 
+0

ToDictionaryの項目の並び順は保証されていません。同じ結果を出力しますか? => x.Key).Select(kvp => $ "{kvp.Key}:{kvp.Value}") '? –

+0

@AkashKavaの問題は注文に関するものではありません。問題は常に存在するとは限らない 'Content-Length'ヘッダーです。 – Luiso

+0

@ Luiso、問題を正確に複製できるように[mcve]を表示できますか?これはあなたの問題に対する解決策を見つけるのに役立ちます。 – Nkosi

答えて

4

あなたの例は不完全です。拡張メソッドを呼び出す前にContentLengthプロパティにアクセスしたときに問題を再現できました。あなたのコードのどこか(ほとんどの場合//残りの設定)あなたは直接的または間接的にそのプロパティを呼び出しています。これはおそらく遅延ロードパターンに従います。次に、あなたがその拡張メソッドを呼び出すときにヘッダーにインクルードされます構築された文字列に含まれます。 Content Lengthプロパティにアクセスする前に手動文字列を生成しているため、一致しません。あなたが明示的にコンテンツの長さを設定しなかった場合は、それを最初にアクセスしようとすると、それはヘッダに(遅延ロード)を、それを追加することがわかりますHttpContentHeaders.ContentLength

public long? ContentLength 
{ 
    get 
    { 
     // 'Content-Length' can only hold one value. So either we get 'null' back or a boxed long value. 
     object storedValue = GetParsedValues(HttpKnownHeaderNames.ContentLength); 

     // Only try to calculate the length if the user didn't set the value explicitly using the setter. 
     if (!_contentLengthSet && (storedValue == null)) 
     { 
      // If we don't have a value for Content-Length in the store, try to let the content calculate 
      // it's length. If the content object is able to calculate the length, we'll store it in the 
      // store. 
      long? calculatedLength = _calculateLengthFunc(); 

      if (calculatedLength != null) 
      { 
       SetParsedValue(HttpKnownHeaderNames.ContentLength, (object)calculatedLength.Value); 
      } 

      return calculatedLength; 
     } 

     if (storedValue == null) 
     { 
      return null; 
     } 
     else 
     { 
      return (long)storedValue; 
     } 
    } 
    set 
    { 
     SetOrRemoveParsedValue(HttpKnownHeaderNames.ContentLength, value); // box long value 
     _contentLengthSet = true; 
    } 
} 

のためのソースコードで

これは、文字列を生成/平滑化した後にContentLengthプロパティにアクセスし、一貫性のない列挙を説明した後で、それに関する私の独自の理論を証明しています。

+0

私はちょうど私のコードをチェックして倍増し、私は 'Content-Length'プロパティにアクセスできる場所を見ることができません。少なくとも明らかなものではありません。 – Luiso

+1

あなたの 'ContentDto'には' Data'プロパティがあります。どのようにあなたはそのプロパティにデータを設定しますか? httoコンテンツのストリームまたは文字列を読み込んでいる場合、ソースコードは、ストリームを読み込む直前に読み込む量を知るためにコンテンツの長さを呼び出します。それはあなたの犯人かもしれません。 – Nkosi

+0

はい、そうです、まさにそれが起こったのです。本当に助けてくれてありがとう – Luiso

0

HttpContentクラスは、ヘッダー・プロパティとはかなり奇妙な行動を持っているようです。何とかコンテンツの長さは、hereと記述されているように計算されているようです。あなたの問題に特に対処するのではなく、最初のものに似た新しいhttpContentオブジェクトでテストを行うことができます。私はかなりあなたが問題なくコンテンツの長さを得ることができると確信しています。

関連する問題