为什么POST和PUT ReadAsAsync()为null,但ReadAsStringAsync()已填充? AKA"如何关闭Chunking?"

时间:2017-02-13 02:14:15

标签: json asp.net-web-api chunked-encoding http-chunked

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

我最近做过的事情突然破坏了所有的POST和PUT。我发现[FromBody]对象我的POST / PUTting到达为空。

所以我的"更新用户"方法看起来像......

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

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

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

...然后obj为null。

但如果我这样做......

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;
  ...

我的&#34; API.GetHttpClient()&#34;例程看起来像这样。您可以看到我在客户端使用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;

 }

我已确认传入的请求是&#34; application / json&#34;的内容类型。和UTF-8。

我在Web服务器上有两个DelegatingHandler,但它们似乎不是问题,因为当我在第一个顶部执行ReadAsAsync()时,它也是null;和ReadAsStringAsync()返回JSON。

那么......我做错了什么?再次,这工作得很好,并且发生了一些变化,所有我的POST和PUT都以这种方式破坏了。

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

最后......当我通过Postman调用此更新PUT时,它可以工作。

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

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

我找不到任何关于如何关闭分块的明确指示。我看到有关闭分块的属性,但这样做并没有帮助。

问题:什么是触发&#34;选择&#34;大块?是客户选择这样做,还是控制器,或两者之间的一些协商?

1 个答案:

答案 0 :(得分:0)

这是一个漫长的过程。

不知道它是怎么到达的,但在我的.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>

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