加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – HttpContent标题不一致的枚举

发布时间:2020-12-15 06:32:20 所属栏目:百科 来源:网络整理
导读:我正在将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.Flatt
我正在将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);
}

而且测试失败,因为Content-Length头没有在我的dto上被捕获.但是,如果我这样做:

[Fact]
public void CanBuild()
{
     var content = new StringContent("some json","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","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没有.我甚至尝试将标头连接到类似Factory的方法,如下所示:

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

看看关于Content-Length头文件的StringContent类是否有特别的东西,但是没有什么区别,无论我是使用构造函数(使用基类HttpContent)还是通用方法FromContent(使用实际的StringContent in这种情况)结果是一样的.

所以我的问题是:

这是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)
 }

解决方法

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

在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属性并解释不一致的枚举.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读