为什么 POST 和 PUT ReadAsAsync() 为空,但 ReadAsStringAsync() 已填充?又名 "How do I turn Chunking Off?"

Why are POSTs and PUTs ReadAsAsync() null, but ReadAsStringAsync() filled? AKA "How do I turn Chunking Off?"

我有一个 Web API 项目,它有几十个 RESTful 方法,在 GET、POST 和 PUT 之间平均分配。系统使用 Entity Framework 对象和 Newtonsoft 的 JSON 来自 Nuget(版本 9.0.1)。

我最近做的一件事突然把所有的POST和PUT都打坏了。我发现我 POST/PUTting 的 [FromBody] 对象作为空值到达。

所以我的 "Update User" 方法看起来是这样的...

    [HttpPut]
    public IHttpActionResult Put([FromBody] User user)

...但是 "user" 总是到达 null。同样,如果我这样做...

  var obj = Request.Content.ReadAsAsync<object>().Result;

...那么 obj 为空。

但是如果我这样做...

var jsonString = Request.Content.ReadAsStringAsync().Result;

...然后我得到预期的 JSON。 (但对于我的架构,我不想要 JSON,我想要对象。)

据我了解,如果某些内容 已经阅读 Request.Content,这就是我所期望的那种行为。内容流是不可倒带的,并设置为最后一个字节;但是 .ReadAsStringAsync() 和 .ReadAsByteArrayAsync() 通过(我假设)复制流并自己处理它来解决这个问题。

我使用 HttpClient 从 WPF 应用程序调用它。调用示例...

using (HttpClient http = API.GetHttpClient())
{
  string url = string.Format("{0}/User", thisApp.WebAPI_BaseUrl);
  RILogManager.Default.SendString("url", url);

  JsonMediaTypeFormatter formatter = new JsonMediaTypeFormatter() ;
  formatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

  HttpResponseMessage response;

  response = http.PutAsync<User>(url, user, formatter, "application/json").Result;
  ...

我的 "API.GetHttpClient()" 例程如下所示。您可以看到我正在使用 DelegateHandler 在客户端做一些 JWT 工作,但我认为这在这里不相关;它不会触及传出请求,只会触及传入响应。

 public static HttpClient GetHttpClient(bool WithAuthToken = true)
 {
     App thisApp = (App)System.Windows.Application.Current;

     //HttpClient http = new HttpClient();
     HttpClient http = HttpClientFactory.Create(new JWTExpirationHandler());

     http.BaseAddress = new Uri(thisApp.WebAPI_BaseUrl);
     http.DefaultRequestHeaders.Accept.Clear();
     http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

     if(WithAuthToken)
         http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", JWT);

     return http;

 }

我已确认传入请求的内容类型为 "application/json" 和 UTF-8。

我在 Web 服务器上有两个 DelegatingHandlers,但它们似乎不是问题,因为当我在第一个的最顶部执行 ReadAsAsync() 时,它也是空的;和 ReadAsStringAsync() returns JSON.

所以...我做错了什么?同样,这工作得很好,有些事情发生了变化,所有 我的 POST 和 PUT 都是这样崩溃的。

我看到一些链接说要从我的 类 中删除 [Serializable]——但这些是我在很多地方使用的 Entity Framework 类,但我没有想那样做。

终于...当我通过 Postman 调用这个 Update PUT 时,它起作用了。

更新
比较来自我自己的客户端和来自 Postman 的 HttpRequests,我发现前者是 "chunked" 而后者不是。这似乎是一个重要的线索。我看到其他一些人也在处理同样的事情:

ASP.NET Web Api - the framework is not converting JSON to object when using Chunked Transfer Encoding

我找不到任何关于如何关闭分块的明确说明。我 do 看到有一个 属性 可以关闭分块,但这样做没有帮助。

问题:是什么触发了 "choice" 分块?是客户端选择这样做,还是控制器,或者两者之间的某种协商?

这是一个漫长的过程。

不知道它是如何到达那里的,但在我的 .csproj 中我有这个:

<Reference Include="System.Net.Http, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
  <HintPath>..\packages\System.Net.Http.4.3.0\lib\net46\System.Net.Http.dll</HintPath>
  <Private>True</Private>
</Reference>

而不是这个:

<Reference Include="System.Net.Http" />

在我的 App.config 我有这个:

  <dependentAssembly>
    <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
  </dependentAssembly>

...而不是...不是这个。我不需要这些东西。我刚拿出来。