我有一个 Web API 项目,它有几十个 RESTful 方法,在 GET、POST 和 PUT 之间平均分配。该系统使用来自 Nuget(版本 9.0.1)的实体框架对象和 Newtonsoft 的 JSON。
我最近做的事情突然破坏了所有的 POST 和 PUT。我发现我正在 POST/PUTting 的 [FromBody] 对象作为空值到达。
所以我的“更新用户”方法看起来像这样......
[HttpPut]
public IHttpActionResult Put([FromBody] User user)
...但是“用户”总是到达空值。同样,如果我这样做...
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;
}
我已经确认传入的请求是“应用程序/json”和 UTF-8 的内容类型。
我在 Web 服务器上有两个 DelegatingHandler,但它们似乎不是问题,因为当我在第一个的最顶部执行 ReadAsAsync() 时,它也是空的;ReadAsStringAsync() 返回 JSON。
所以......我做错了什么?再一次,这很好用,并且发生了一些变化,我所有的 POST 和 PUT 都以这种方式中断了。
我看到一些链接说要从我的类中删除 [Serializable] ——但这些是我在很多地方使用的实体框架类,我不想这样做。
最后...当我通过 Postman 调用此 Update PUT 时,它可以工作。
更新
比较来自我自己的客户端和 Postman 的 HttpRequest,我发现前者是“分块的”,而后者不是。这似乎是一个重要的线索。我看到其他一些人也在处理同样的问题:
ASP.NET Web Api - 使用分块传输编码时,框架未将 JSON 转换为对象
我找不到任何关于如何关闭分块的明确指示。我确实看到有一个属性可以关闭分块,但这样做并没有帮助。
问题:是什么触发了块的“选择”?是客户选择这样做,还是控制器,还是两者之间的某种协商?