ASP.NET Core 3.0 [FromBody] 字符串内容 returns "The JSON value could not be converted to System.String."

ASP.NET Core 3.0 [FromBody] string content returns "The JSON value could not be converted to System.String."

在 ASP.NET Core 3.0 中的 ApiController 上使用 [FromBody] 字符串内容 returns 验证错误:

{"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
 "title":"One or more validation errors occurred.",
 "status":400,
 "traceId":"|9dd96d96-4e64bafba4ba0245.",
 "errors":{"$":["The JSON value could not be converted to System.String. Path: $ | LineNumber: 0 | BytePositionInLine: 1."]}}

当客户端 post 数据的内容类型为:application/json

如何在 .NET Core 3.0 的 api 控制器中获取原始 json 数据作为字符串?客户端无需更新其内容类型?

不确定这是否有帮助,但我认为他们对 .net core 3.0 Newtonsoft.JSON 包做了一些更改,所以你可以试试这个

安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson 包。

在你的 startup.cs 中添加

services.AddControllers().AddNewtonsoftJson();

您需要将Json 对象转换为字符串,然后将其发送到服务器。像 JSON.stringify(jsonObj).

我必须编写自定义 IInputFormatter 以确保我的正文内容始终被解释为字符串。

我也遇到过无法更新所有 API 客户端的情况。

以下内容将确保任何 [FromBody] 参数都将被解释为字符串,即使它们没有被调用者用引号括起来。

public class JsonStringInputFormatter : TextInputFormatter
{
    public JsonStringInputFormatter() : base()
    {
        SupportedEncodings.Add(UTF8EncodingWithoutBOM);
        SupportedEncodings.Add(UTF16EncodingLittleEndian);

        SupportedMediaTypes.Add(MediaTypeNames.Application.Json);
    }

    public override bool CanRead(InputFormatterContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        return context.ModelType == typeof(string);
    }

    public override async Task<InputFormatterResult> ReadRequestBodyAsync(
        InputFormatterContext context, Encoding encoding)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        using (var streamReader = new StreamReader(
            context.HttpContext.Request.Body,
            encoding))
        {
            return await InputFormatterResult.SuccessAsync(
                (await streamReader.ReadToEndAsync()).Trim('"'));
        }
    }
}

修剪正文中的引号使其能够向前兼容格式正确且引号包裹的正文内容。

确保它在 System.Text.Json 格式化程序之前在您的启动中注册:

services.AddControllers()
    .AddMvcOptions(options =>
    {
        options.InputFormatters.Insert(
            0,
            new JsonStringInputFormatter());
    });

如果您使用的是 asp.net 核心 3.0,那么它具有内置的 JSON 支持。我使用了以下内容,无需设置自定义输入处理程序即可工作。

[HttpPost]
public async Task<IActionResult> Index([FromBody] JsonElement body)
{

    string json = System.Text.Json.JsonSerializer.Serialize(body);
    return Ok();

}

[FromBody] string content 更改为 [FromBody] object content,然后如果您 want/need 读取为字符串,请使用 content.ToString()

如果您将参数 [FromBody] String value 更改为 [FromBody] YourType value,它会自动为您反序列化。

发件人:

// POST api/<SelectiveCallRulesController>
[HttpPost]
public async Task Post([FromBody] String rule)        
{
...

收件人:

// POST api/<SelectiveCallRulesController>
[HttpPost]
public async Task Post([FromBody] SelectiveCallRule rule)        
{
...

这让我四处寻找,直到我意识到关于反序列化的错误消息是正确的!

您可以创建另一个 class 包含您的 json 字段。

使用 JsonElement 而不是字符串或对象。 {yourcontrollername([FromBody] JsonElement yourJsondata)}