WebApi2 Controller Post 方法总是接收 null FromBody
WebApi2 Controller Post method always receiving null FromBody
我的 POST 方法中的 [FromBody] 始终为空。
我在 VS2019 中使用一个最小的应用程序复制了它:
- 创建项目ASP.NET Web 应用程序(.NET Framework)
- Select 网页 API
这将使用以下方法创建一个带有 ValuesController class 的骨架项目:
public void Post([FromBody] string value)
{
}
我 运行 在“IIS Express (Google Chrome)”中启动这个项目并浏览到 https://localhost:44358/api/values 工作正常并命中 Get 方法中的断点。
然后我尝试使用 cUrl POST 数据:
curl --header "Content-Type: application/json" --url https://localhost:44358/api/values --data "wibble"
VS2019下了断点,但值为空(我预计是“wibble”)。
我可以在请求内容中看到长度为6,这会根据我传递给数据的字符串的长度而变化,但是会调用读取它return空字符串,或者一个字节[] 个零。
this.Request.Content.ReadAsStringAsync().Result ""
this.Request.Content.Headers.ContentType {application/json}
this.Request.Content.Headers.ContentLength 6
尝试从另一个使用 HttpClient 的 C# 应用程序 POST 也显示相同的结果。
我错过了什么?这个问题出现在默认的骨架应用程序中,而且每个人都没有抱怨它,这表明它一定是显而易见的,但是...
更新
我在 Fiddler 中看到了同样的问题,但我已经使用以下方法让它与 HttpClient 一起工作:
client.PostAsync<string>(url, "wibble", new JsonMediaTypeFormatter()).Result;
但以下内容不起作用(接收为 null):
client.PostAsync(url, new StringContent("wibble", Encoding.UTF8), new JsonMediaTypeFormatter()).Result;
更改生成的代码来自:
public void Post([FromBody] string value) { ... }
至:
public void Post([FromBody] MyClass value) { ... }
现在可以使用标准的 cUrl / Fiddler / Javascript / etc POST.
所以我想问题在于尝试自动将字符串转换为对象,这可以解释为什么很多人没有遇到这个问题。
如果您确实想要 POST 文本,自动生成的控制器(看起来应该可以满足您的要求)不起作用。
要解决这个问题,请将 Post 方法更改为:
public void Post()
{
string value = Request.Content.ReadAsStringAsync().Result;
...
}
现在没有 [FromBody]
意味着 Request.Content.ReadAsStringAsync()
returns 内容符合预期。
总结:
[Route("api/values/obj")]
public void Post([FromBody] MyObject value) /* OK */
{
...
}
[Route("api/values/str")]
public void Post([FromBody] string value) /* FAIL */
{
...
}
[Route("api/values/str2")]
public void Post() /* OK */
{
string value = Request.Content.ReadAsStringAsync().Result;
...
}
cUrl 的结果如下:
curl "http://localhost:59801/api/Values/obj" --header "Content-Type: application/json" --data "{id:1, name:'Andy'}"
好的
curl "http://localhost:59801/api/Values/str2" --header "Content-Type: text/plain" --data "wibble"
好的
curl "http://localhost:59801/api/Values/str2" --header "Content-Type: application/json" --data "wobble"
好的
curl "http://localhost:59801/api/Values/str" --header "Content-Type: text/plain" --data "wibble"
失败。异常“此资源不支持请求实体的媒体类型 'text/plain'。”
curl "http://localhost:59801/api/Values/str" --header "Content-Type: application/json" --data "wobble"
失败。值为空。
我的 POST 方法中的 [FromBody] 始终为空。
我在 VS2019 中使用一个最小的应用程序复制了它:
- 创建项目ASP.NET Web 应用程序(.NET Framework)
- Select 网页 API
这将使用以下方法创建一个带有 ValuesController class 的骨架项目:
public void Post([FromBody] string value)
{
}
我 运行 在“IIS Express (Google Chrome)”中启动这个项目并浏览到 https://localhost:44358/api/values 工作正常并命中 Get 方法中的断点。
然后我尝试使用 cUrl POST 数据:
curl --header "Content-Type: application/json" --url https://localhost:44358/api/values --data "wibble"
VS2019下了断点,但值为空(我预计是“wibble”)。
我可以在请求内容中看到长度为6,这会根据我传递给数据的字符串的长度而变化,但是会调用读取它return空字符串,或者一个字节[] 个零。
this.Request.Content.ReadAsStringAsync().Result ""
this.Request.Content.Headers.ContentType {application/json}
this.Request.Content.Headers.ContentLength 6
尝试从另一个使用 HttpClient 的 C# 应用程序 POST 也显示相同的结果。
我错过了什么?这个问题出现在默认的骨架应用程序中,而且每个人都没有抱怨它,这表明它一定是显而易见的,但是...
更新
我在 Fiddler 中看到了同样的问题,但我已经使用以下方法让它与 HttpClient 一起工作:
client.PostAsync<string>(url, "wibble", new JsonMediaTypeFormatter()).Result;
但以下内容不起作用(接收为 null):
client.PostAsync(url, new StringContent("wibble", Encoding.UTF8), new JsonMediaTypeFormatter()).Result;
更改生成的代码来自:
public void Post([FromBody] string value) { ... }
至:
public void Post([FromBody] MyClass value) { ... }
现在可以使用标准的 cUrl / Fiddler / Javascript / etc POST.
所以我想问题在于尝试自动将字符串转换为对象,这可以解释为什么很多人没有遇到这个问题。
如果您确实想要 POST 文本,自动生成的控制器(看起来应该可以满足您的要求)不起作用。
要解决这个问题,请将 Post 方法更改为:
public void Post()
{
string value = Request.Content.ReadAsStringAsync().Result;
...
}
现在没有 [FromBody]
意味着 Request.Content.ReadAsStringAsync()
returns 内容符合预期。
总结:
[Route("api/values/obj")]
public void Post([FromBody] MyObject value) /* OK */
{
...
}
[Route("api/values/str")]
public void Post([FromBody] string value) /* FAIL */
{
...
}
[Route("api/values/str2")]
public void Post() /* OK */
{
string value = Request.Content.ReadAsStringAsync().Result;
...
}
cUrl 的结果如下:
curl "http://localhost:59801/api/Values/obj" --header "Content-Type: application/json" --data "{id:1, name:'Andy'}"
好的
curl "http://localhost:59801/api/Values/str2" --header "Content-Type: text/plain" --data "wibble"
好的
curl "http://localhost:59801/api/Values/str2" --header "Content-Type: application/json" --data "wobble"
好的
curl "http://localhost:59801/api/Values/str" --header "Content-Type: text/plain" --data "wibble"
失败。异常“此资源不支持请求实体的媒体类型 'text/plain'。”
curl "http://localhost:59801/api/Values/str" --header "Content-Type: application/json" --data "wobble"
失败。值为空。