如果使用 FromBody 和 FromForm 参数始终为 null/new,则对 Core API 的 Webclient 调用找不到端点
Webclient call to Core API can't find endpoint if using FromBody and FromForm parameter is always null/new
这是 API 代码片段:
[HttpPost]
[ProducesResponseType(typeof(myObject), 201)] //created
[ProducesResponseType(500)] //server error
public IActionResult Create([FromForm]myObject myObj) {
...
这是服务器端调用:
...
using (WebClient client = new WebClient()) {
NameValueCollection formData = new NameValueCollection();
string targetURL = "https://localhost:44317/api/MyController/Create"
string callMethod = "POST";
formData["myObj"] = JsonConvert.SerializeObject(myObj);
var thingy = client.UploadValues(targetURL, callMethod, formData);
...
如果我使用 [FromForm]
,调用会找到端点,但传入的数据就像我说的 myObj = new MyObject();
一样,所有内容都具有默认值。所以... 完全 不为空。
如果我使用 [FromBody]
,client
找不到 url,我得到一个 400 Bad Request
。
我已经阅读了这里和其他地方的大量帖子,但我认为它们并没有完全涵盖这种情况,因为我观察到的似乎与其他人的要求相反。所以我不确定我的代码发生了什么。
请注意,我不能使用 async,所以我不能使用 HttpClient。 (不能使用异步,因为这是 Kentico 站点内部,这是门户页面内部的 ascx)
你的 FromForm
问题是你将它序列化为字符串,默认情况下 WebAPI 不会为你反序列化它。如果你想继续 FromForm
你可以将参数类型更改为字符串并显式反序列化它:
public IActionResult Create([FromForm]string myObj) {
myObject obj = JsonConvert.DeserializeObject<myObject>(myObj);
...
看起来你打算 post JSON,但你实际上 posting 作为 x-www-form-urlencoded
序列化的 JSON 作为值对于 myObj
参数。由于编码类型的原因,该操作必须使用 [FromForm]
(或根本没有属性),但此时它无法将您的 "JSON" 反序列化为对象。我在这里用引号括起 "JSON" 因为实际上它只是一个字符串。 ASP.NET Core 根本不知道这甚至是 JSON,也不应该对它做些什么。总之,您需要 post 一个实际的 application/json
请求正文。
using (var client = new WebClient())
{
client.Headers["Content-Type"] = "application/json; charset=utf-8";
var requestBody = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(myObj));
var response = webClient.UploadData(targetUrl, callMethod, requestBody);
}
然后,当然,您需要在参数上实际使用 FromBody
属性,因为现在您实际上会收到 JSON.
这是 API 代码片段:
[HttpPost]
[ProducesResponseType(typeof(myObject), 201)] //created
[ProducesResponseType(500)] //server error
public IActionResult Create([FromForm]myObject myObj) {
...
这是服务器端调用:
...
using (WebClient client = new WebClient()) {
NameValueCollection formData = new NameValueCollection();
string targetURL = "https://localhost:44317/api/MyController/Create"
string callMethod = "POST";
formData["myObj"] = JsonConvert.SerializeObject(myObj);
var thingy = client.UploadValues(targetURL, callMethod, formData);
...
如果我使用 [FromForm]
,调用会找到端点,但传入的数据就像我说的 myObj = new MyObject();
一样,所有内容都具有默认值。所以... 完全 不为空。
如果我使用 [FromBody]
,client
找不到 url,我得到一个 400 Bad Request
。
我已经阅读了这里和其他地方的大量帖子,但我认为它们并没有完全涵盖这种情况,因为我观察到的似乎与其他人的要求相反。所以我不确定我的代码发生了什么。
请注意,我不能使用 async,所以我不能使用 HttpClient。 (不能使用异步,因为这是 Kentico 站点内部,这是门户页面内部的 ascx)
你的 FromForm
问题是你将它序列化为字符串,默认情况下 WebAPI 不会为你反序列化它。如果你想继续 FromForm
你可以将参数类型更改为字符串并显式反序列化它:
public IActionResult Create([FromForm]string myObj) {
myObject obj = JsonConvert.DeserializeObject<myObject>(myObj);
...
看起来你打算 post JSON,但你实际上 posting 作为 x-www-form-urlencoded
序列化的 JSON 作为值对于 myObj
参数。由于编码类型的原因,该操作必须使用 [FromForm]
(或根本没有属性),但此时它无法将您的 "JSON" 反序列化为对象。我在这里用引号括起 "JSON" 因为实际上它只是一个字符串。 ASP.NET Core 根本不知道这甚至是 JSON,也不应该对它做些什么。总之,您需要 post 一个实际的 application/json
请求正文。
using (var client = new WebClient())
{
client.Headers["Content-Type"] = "application/json; charset=utf-8";
var requestBody = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(myObj));
var response = webClient.UploadData(targetUrl, callMethod, requestBody);
}
然后,当然,您需要在参数上实际使用 FromBody
属性,因为现在您实际上会收到 JSON.