Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# HttpContent标头枚举不一致_C#_Http Headers_Dotnet Httpclient_Httpcontent - Fatal编程技术网

C# HttpContent标头枚举不一致

C# HttpContent标头枚举不一致,c#,http-headers,dotnet-httpclient,httpcontent,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 = conte

我正在将
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上捕获
内容长度
标题,该测试失败。但是,如果我这样做:

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

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

你的例子不完整。只有在调用扩展方法之前访问
ContentLength
属性时,我才能重新创建您的问题。在代码中的某个地方(很可能//安装程序的其余部分),您直接或间接地调用该属性,该属性很可能遵循延迟加载模式,然后在下次调用扩展方法时将其包含在头中,并包含在构造的字符串中。它们不匹配,因为您正在访问content length属性之前生成手动字符串

在源代码中

您可以看到,如果您没有显式设置内容长度,那么当您第一次尝试访问它时,它会将它(延迟加载)添加到标题中


这证明了我最初的理论,即在生成/展平字符串,然后访问
ContentLength
属性后添加它,并解释了不一致的枚举。

ToDictionary中的项目顺序不保证,这是否会产生相同的结果
headers.ToDictionary(h=>h.Key,h=>string.Join(;”,h.Value)).Orderby(x=>x.Key)。选择(kvp=>$“{kvp.Key}:{kvp.Value}”)
?@AkashKava问题与顺序无关。问题是
内容长度
标题并不总是在那里。@Luiso,您能否显示一个标题,以便可以准确地复制您的问题。这将有助于找到您问题的解决方案。我刚刚双重检查了我的代码,我看不到我可以在哪里访问
Content Length
属性,至少不是一个明显的属性,但我可能只是缺少它。非常感谢您在您的
内容中注意到您有一个
数据
属性。如何以及在何处填充该属性。如果您正在读取htto内容的流或字符串,那么源代码显示,在读取流之前,它会调用内容长度,以了解要读取多少内容。那可能是你的罪魁祸首。是的,你是对的,事情就是这样。你帮了大忙,非常感谢
 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)
 }
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;
    }
}