为什么POST和PUT ReadAsAsync()为空,而ReadAsStringAsync()被填充?又称为“如何关闭分块?" [英] Why are POSTs and PUTs ReadAsAsync() null, but ReadAsStringAsync() filled? AKA "How do I turn Chunking Off?"

查看:290
本文介绍了为什么POST和PUT ReadAsAsync()为空,而ReadAsStringAsync()被填充?又称为“如何关闭分块?"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a Web API project that has a few dozen RESTful methods, split about evenly between GETs, POSTs and PUTs. The system uses Entity Framework objects and Newtonsoft's JSON from Nuget (version 9.0.1).

我最近做的事情突然破坏了所有POST和PUT.我发现我正在POST/PUTTING的[FromBody]对象以null到达.

Something I've done recently has suddenly broken all the POSTs and PUTs. I find that the [FromBody] objects I'm POST/PUTting arrive as null.

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

So my "Update User" method looks like so...

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

...但是用户"始终为空.同样,如果我这样做...

...but "user" always arrives null. Likewise if I do this...

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

...然后obj为空.

...then obj is null.

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

But if I do this...

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

...然后我得到了预期的JSON. (但是对于我的体系结构,我不需要JSON,我想要对象.)

...then I get the expected JSON. (But for my architecture, I don't want the JSON, I want the object.)

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

From what I understand, this is the kind of behavior that I'd expect if something has already read the 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.

我使用HttpClient从WPF应用程序中调用它.样品通话...

I call this from a WPF application using HttpClient. 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;
  ...

我的"API.GetHttpClient()"例程看起来像这样.您可以看到我正在使用DelegateHandler在客户端进行一些JWT工作,但是我认为这与这里无关.它不涉及传出的请求,仅涉及传入的响应.

My "API.GetHttpClient()" routine looks like this. 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; 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;

 }

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

I've confirmed that the incoming request is Content-type of "application/json" and UTF-8.

我在Web服务器上有两个DelegatingHandlers,但这似乎不是问题,因为当我在第一个的顶部执行ReadAsAsync()时,它也为null.然后ReadAsStringAsync()返回JSON.

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; and ReadAsStringAsync() returns the JSON.

那么...我在做什么错?再次,这很好用,并且发生了一些变化, all 我的POST和PUT都这样破坏了.

So...what am I doing wrong? Again, this was working great, and something changed and all my POSTs and PUTs broke this way.

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

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.

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

Finally...when I call this Update PUT through Postman, it works.

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

UPDATE
Comparing the HttpRequests from my own client, and from Postman, I see that the former are "chunked" and the latter are not. This seems an important clue. I see some other folks dealing with the same:

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.

问题:是什么触发选择"的成块?是客户选择执行此操作,还是选择Controller,还是两者之间进行一些协商?

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?

推荐答案

那是一个漫长的过程.

That was a long haul.

不知道它是怎么到达那里的,但是在我的.csproj中,我有这个东西:

Don't know how it got there, but in my .csproj I had this:

<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中,我有这个:

And in my App.config I had this:

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

这篇关于为什么POST和PUT ReadAsAsync()为空,而ReadAsStringAsync()被填充?又称为“如何关闭分块?"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆