尝试调用控制器端点时“无法将 JSON 值转换为 System.String”

Pla*_*pus 9 c# rest .net-core asp.net-core

我一直在尝试创建一个简单的 API,我设法使Get工作正常进行,但是每当我尝试使用它PostPut无法使其工作时。
我正在尝试发布/放置一个 JSON 并将其作为字符串获取到我的控制器中。
我正在使用 Postman 和 Insomnia 进行测试(因为我在本地运行,所以我对两者都关闭了 SSL 验证)。
这是我的控制器:

[Route("backoffice/[controller]")]
[ApiController]
public class AddQuestionController : ControllerBase
{
    private IQuestionRepository _questionRepository;

    public AddQuestionController(IQuestionRepository questionRepository)
    {
        _questionRepository = questionRepository ?? throw new ArgumentNullException(nameof(questionRepository));

    }

    [ProducesResponseType((int)System.Net.HttpStatusCode.OK)]
    [HttpPost]
    public async Task<ActionResult> AddQuestion([FromBody] string question)
    {
        Question q = JsonConvert.DeserializeObject<Question>(question);
        await Task.Run(() => _questionRepository.InsertOne(q));
        return Ok();
    }
}
Run Code Online (Sandbox Code Playgroud)

邮差

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

所以后来我认为这是因为Json邮递员中的格式。但后来我尝试了这种text格式,结果发生了:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.13",
    "title": "Unsupported Media Type",
    "status": 415,
    "traceId": "|a0b79873-4e41e975d19e251e."
}
Run Code Online (Sandbox Code Playgroud)

每次它甚至没有到达我的控制器的第一行。有人能告诉我我在这里做错了什么吗?是我的控制器吗?这是我使用 Postman 的方式吗?

Nko*_*osi 16

模型绑定器无法将发送的数据映射/绑定到控制器参数

您的操作需要来自请求正文的简单字符串

public async Task<ActionResult> AddQuestion([FromBody] string question)
Run Code Online (Sandbox Code Playgroud)

但是你发送了一个复杂的对象

{ "test" : "test" }
Run Code Online (Sandbox Code Playgroud)

如果属性名称匹配,您可能已经匹配

例如

{ "question" : "test" }
Run Code Online (Sandbox Code Playgroud)

由于模型绑定器在匹配参数时会考虑属性名称。

如果你想接收一个原始字符串,那么你需要发送一个有效的原始 JSON 字符串

"{ \"test\": \"test \"}"
Run Code Online (Sandbox Code Playgroud)

那是正确的逃脱。

另一种选择是使用复杂的对象作为参数

class Question  {
    public string test { get; set; }
    //...other properties
}
Run Code Online (Sandbox Code Playgroud)

匹配预期数据

public async Task<ActionResult> AddQuestion([FromBody] Question question) {
    string value = question.test;

    //...
}
Run Code Online (Sandbox Code Playgroud)

模型绑定器将绑定数据并将其传递给操作参数。

ASP.NET Core 中的参考模型绑定