HttpContent标头不一致的枚举

时间:2016-07-24 16:56:11

标签: c# http-headers dotnet-httpclient httpcontent

我正在将HttpContent转换为以下dto:

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

该测试失败,因为我的dto没有捕获Content-Length标题。但是,如果我这样做:

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

它失败,因为dto没有Content-Length标题,但是dto1。我甚至尝试在类似工厂的方法中获取标题,如下所示:

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

查看关于StringContent标题的Content-Length类是否有特殊内容,但无论是否使用构造函数(使用基类{{1})都没有区别})或泛型方法HttpContent(在这种情况下使用实际的StringContent)结果是相同的。

所以我的问题是:

这是FromContent的预期行为吗? 是否有一些特定于实际HttpContent.Headers类型的标题?
我在这里错过了什么?

注意:这是HttpContent扩展方法的代码:

Flatten

2 个答案:

答案 0 :(得分:4)

你的例子不完整。在调用扩展方法之前访问public static void main(String[] args) { // TODO Auto-generated method stub boolean status = true; int numberToStore = status?1:0; System.out.println(numberToStore); } 属性时,我只能重新创建您的问题。你的代码中的某个地方(很可能是//其余的设置)你直接或间接地调用那个很可能遵循延迟加载模式的属性,然后当你调用它时它会包含在标题中你的扩展方法,它包含在构造的字符串中。它们不匹配,因为您在访问内容长度属性之前生成了手动字符串。

HttpContentHeaders.ContentLength

的源代码中
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; } } 属性并解释不一致的枚举后添加它。

答案 1 :(得分:0)

似乎HttpContent类对headers属性有一个非常奇怪的行为。不知何故,内容长度似乎按照here所述进行计算。它没有具体解决您的问题,但您可以使用与初始类似的新httpContent对象进行测试。我很确定你能够毫无问题地获得内容长度。