API控制器无法从POST正文读取Json

时间:2018-11-05 14:27:10

标签: c# asp.net-core asp.net-core-2.0 asp.net-core-webapi

背景

我正在将自己体内的JSON发送给API控制器,但始终收到以下错误。

  

{“”:[“解析值时遇到意外字符:{。路径   ”,第1行,位置1。“]}

我的HTTP请求

HttpClient client = new HttpClient();
HttpRequest httpRequest;
HttpResponseMessage httpResponse = null;
httpRequest = new HttpRequest("", HostnameTb.Text, null);

var values = new Dictionary<string, string>
{
    { "APIKey", APIKeyTb.Text }
};

string json = JsonConvert.SerializeObject(values);
StringContent content = new StringContent(json.ToString(), Encoding.UTF8, "application/json");
httpResponse = client.PostAsync(HostnameTb.Text, content).Result;

var responseString = await httpResponse.Content.ReadAsStringAsync();

我的控制器看起来像这样。

[HttpPost]
public void Post([FromBody] string value)
{
  //Never gets here.
}

体内的Json。

  

{“ APIKey”:“ 1283f0f8 ...”}

问题

我宁愿使用.Net Core [From Body]功能,而不是手动获取内容。

我希望JSON字符串在字符串Value参数中可用。

我想念什么?

3 个答案:

答案 0 :(得分:3)

ASP.NET Core尝试将JSON中的{"APIKey":"1283f0f8..."}反序列化为string值,并失败了,因为它期望输入是有效的JSON字符串。

换句话说,如果您的身体是"{\"APIKey\":\"1283f0f8...\"}",则可以按预期在输入变量中包含JSON字符串。

为了在不更改HTTP请求的情况下获取APIKey值,请创建输入类型:

public class Input
{
    public string ApiKey { get; set; }
}

并将其用作控制器操作的输入:

[HttpPost]
public void Post([FromBody] Input input)
{
    var apiKey = input.ApiKey;
    // etc
}

或者,更改HTTP请求以发送string

// ...
var content = new StringContent(JsonConvert.SerializeObject(json), Encoding.UTF8, "application/json");
// ...

请注意使用JsonConvert.SerializeObject()代替ToString()"foo".ToString()仍然只是"foo",而您想要"\"foo\""

答案 1 :(得分:1)

这不是这样的。 [FromBody]调用序列化程序以反序列化请求正文。然后,模型绑定器尝试将其绑定到参数。在这里,它不能这样做,因为您要绑定到字符串,并且请求正文是字典。本质上,幕后发生的事情(伪代码)是:

value = JsonConvert.DeserializeObject<string>(dictionaryAsJson);

您从JSON.NET中收到反序列化错误,因为它无法将JSON解析为字符串。

如果您希望该值作为字符串,则应该以{{1​​}}之类而不是text/plain的形式发布。否则,您将需要绑定到实际表示要传入的JSON对象的类型,此处为application/json

答案 2 :(得分:0)

我在ASP.NET Core 3.1中遇到了同样的问题。我正在将JSON发布到我的API控制器,如下所示:

public JsonResult Save([FromBody]MainDetails obj){ ... }

我的问题是我的ChildDetails.StartDate对象的属性MainDetails的类型为DateTime,并且我正在使用JSON发送一个null值。这导致控制器上的反序列化失败。我将属性类型从DateTime?更改为DateTime以使其起作用。

基本上,需要检查并确保您发布的JSON对要反序列化的目标对象有效。如果您具有JSON中发送的值为null的不可为null的属性,则反序列化将失败(不告诉您原因)。 希望这会有所帮助。