简体   繁体   English

为什么POST和PUT ReadAsAsync()为空,但ReadAsStringAsync()已填充? 又称为“如何关闭分块?”

[英]Why are POSTs and PUTs ReadAsAsync() null, but ReadAsStringAsync() filled? AKA “How do I turn Chunking Off?”

I have a Web API project that has a few dozen RESTful methods, split about evenly between GETs, POSTs and PUTs. 我有一个Web API项目,该项目具有数十种RESTful方法,在GET,POST和PUT之间平均分配。 The system uses Entity Framework objects and Newtonsoft's JSON from Nuget (version 9.0.1). 系统使用Entity Framework对象和Nuget(版本9.0.1)中的Newtonsoft的JSON。

Something I've done recently has suddenly broken all the POSTs and PUTs. 我最近完成的操作突然破坏了所有POST和PUT。 I find that the [FromBody] objects I'm POST/PUTting arrive as null. 我发现我正在POST / PUTTING的[FromBody]对象以null形式到达。

So my "Update User" method looks like so... 所以我的“更新用户”方法看起来像这样...

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

...but "user" always arrives null. ...但是“用户”总是到达null。 Likewise if I do this... 同样如果我这样做...

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

...then obj is null. ...那么obj为空。

But if I do this... 但是如果我这样做

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

...then I get the expected JSON. ...然后我得到了预期的JSON。 (But for my architecture, I don't want the JSON, I want the object.) (但是对于我的体系结构,我不需要JSON,我想要对象。)

From what I understand, this is the kind of behavior that I'd expect if something has already read the Request.Content. 据我了解,如果某些内容已经读取了Request.Content,这就是我期望的行为。 The Content stream is non-rewindable, and gets set to the last byte; 内容流不可倒带,并设置为最后一个字节; but .ReadAsStringAsync() and .ReadAsByteArrayAsync() get around this by (I presume) copying the stream and handling it themselves. 但是.ReadAsStringAsync()和.ReadAsByteArrayAsync()通过(我认为)复制流并自己处理流来解决此问题。

I call this from a WPF application using HttpClient. 我从使用HttpClient的WPF应用程序调用此方法。 Sample call... 样品通话...

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

My "API.GetHttpClient()" routine looks like this. 我的“ API.GetHttpClient()”例程如下所示。 You can see I'm doing some JWT work on the client-side with a DelegateHandler, but I don't think that's pertinent here; 您可以看到我正在使用DelegateHandler在客户端进行一些JWT工作,但是我认为这并不重要。 it doesn't touch the outgoing request, just the incoming response. 它不涉及传出的请求,仅涉及传入的响应。

 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;

 }

I've confirmed that the incoming request is Content-type of "application/json" and UTF-8. 我已经确认传入请求是“ application / json”和UTF-8的Content-type。

I have two DelegatingHandlers on the web server, but they don't seem to be the problem, because when I do the ReadAsAsync() at the very top of the first one, it's also null; 我在Web服务器上有两个DelegatingHandlers,但这似乎不是问题,因为当我在第一个的顶部执行ReadAsAsync()时,它也为null。 and ReadAsStringAsync() returns the JSON. ReadAsStringAsync()返回JSON。

So...what am I doing wrong? 所以...我在做什么错? Again, this was working great, and something changed and all my POSTs and PUTs broke this way. 再次,这很好,并且发生了一些变化,我所有的 POST和PUT都以这种方式破坏了。

I saw some links that said to remove [Serializable] from my classes--but these are Entity Framework classes that I use in many places, and I don't want to do that. 我看到一些链接说要从我的类中删除[Serializable],但是这些链接是我在很多地方使用的Entity Framework类,所以我不想这样做。

Finally...when I call this Update PUT through Postman, it works. 最后...当我通过邮递员将此更新称为PUT时,它可以工作。

UPDATE UPDATE
Comparing the HttpRequests from my own client, and from Postman, I see that the former are "chunked" and the latter are not. 比较我自己的客户端和Postman的HttpRequest,我发现前者是“分块的”,而后者则不是。 This seems an important clue. 这似乎是一个重要的线索。 I see some other folks dealing with the same: 我看到其他一些人正在处理相同的问题:

ASP.NET Web Api - the framework is not converting JSON to object when using Chunked Transfer Encoding ASP.NET Web Api-使用分块传输编码时,框架未将JSON转换为对象

I cannot find any clear indication of how to turn chunking off. 我找不到任何有关如何关闭分块的明确指示。 I do see that there's a property to turn off chunking, but doing that doesn't help. 确实看到有一个属性可以关闭分块,但是这样做没有帮助。

Question: What is triggering the "choice" to chunk? 问题:触发“选择”的原因是什么? Is it the client choosing to do this, or the Controller, or some negotiation between the two? 是客户选择执行此操作,还是选择Controller,还是两者之间进行一些协商?

That was a long haul. 那是一个漫长的过程。

Don't know how it got there, but in my .csproj I had this: 不知道它是怎么到达那里的,但是在我的.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>

Rather than this: 而不是这样:

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

And in my App.config I had this: 在我的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>

...rather than... not this. ...而不是... 不是这个。 I didn't need this stuff. 我不需要这个东西。 I just took it out. 我刚拿出来

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM