ASP.NET Core 3.1 Web Api HttpPost Action 参数无法接收 axios application/json HttpPost 传递数据

Posted

技术标签:

【中文标题】ASP.NET Core 3.1 Web Api HttpPost Action 参数无法接收 axios application/json HttpPost 传递数据【英文标题】:ASP.NET Core 3.1 Web Api HttpPost Action parameter can't receive axios application/json HttpPost passing data 【发布时间】:2021-08-27 01:36:30 【问题描述】:

我以前使用Controller而不是ApiController,今天我尝试使用ApiController,发现下面的问题。

ASP.NET Core Web Api HttpPost Action 参数无法接收 axios application/json post 传递数据

asp.net核心api代码

[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase

    [HttpPost]
    public async Task<IActionResult> Post(string json)
    
        return this.Ok();
    

前端

var json = '"json_data":"\"value\":\"hello world\"';
axios.post('Test', "json": json)
    .then(function (response) 
        console.log(response);
    )
    .catch(function (error) 
        console.log(error);
    );   

实际要求

Accept:application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Content-Type: application/json;charset=UTF-8
Request Payload : 
"json_data":"\"value\":\"hello world\"

实际动作json参数数据为null 预期接收数据:"json_data":"\"value\":\"hello world\"


更新

我尝试了下面的代码,我得到 rawValue value = "json_data":"\"value\":\"hello world\" 但 json value = null

[HttpPost]
public async Task<IActionResult> Post(string json)

    using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
    
        string rawValue = await reader.ReadToEndAsync();
    

【问题讨论】:

【参考方案1】:

公共异步任务发布(字符串 json)

如果您想使用数据从前端发出 HTTP 请求并将其正确绑定到 string-type ACTION 参数,您可以尝试实现并使用自定义纯文本输入格式化程序。

public class TextPlainInputFormatter : TextInputFormatter

    public TextPlainInputFormatter()
    
        SupportedMediaTypes.Add("text/plain");
        SupportedEncodings.Add(UTF8EncodingWithoutBOM);
        SupportedEncodings.Add(UTF16EncodingLittleEndian);
    

    protected override bool CanReadType(Type type)
    
        return type == typeof(string);
    

    public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
    
        string data = null;
        using (var streamReader = new StreamReader(context.HttpContext.Request.Body))
        
            data = await streamReader.ReadToEndAsync();
        
        return InputFormatterResult.Success(data);
    

配置和添加自定义格式化程序支持

services.AddControllers(opt => opt.InputFormatters.Insert(0, new TextPlainInputFormatter()));

前端代码

const headers = 
    'Content-Type': 'text/plain'
;

var json = '"json_data":"\"value\":\"hello world\"';

axios.post('test', json,  headers: headers )
    .then(function (response) 
        //...

测试结果

【讨论】:

【参考方案2】:

更新:

Demo Source Code Link

我终于用[FromBody]System.Text.Json.JsonElement解决了问题

[HttpPost]
[Route("TestUsingFromBodyAttribute")]
public object TestUsingFromBodyAttribute([FromBody] System.Text.Json.JsonElement content)

    return content;

因为axios默认Content-Type: application/x-www-form-urlencoded 需要更新Content-Type': 'application/json,否则系统会显示415 unsupported media type

然后就不能使用string类型或者系统会显示400 bad request

因为asp.net核心检查Content-Type': 'application/json并使用[FromBody]会自动转换为json对象(System.Text.Json.JsonElement),所以它不能使用字符串类型。

如果不想编辑axios默认Content-Type: application/x-www-form-urlencoded,则必须设置reqeust data is object not string

阅读:

https://weblog.west-wind.com/posts/2017/sep/14/accepting-raw-request-body-content-in-aspnet-core-api-controllers

早期答案:

现在我使用Request.Body而不是Action Parameter来解决问题,但我仍然不知道为什么它不能做到。

[HttpPost]
public async Task<IActionResult> Post()

    string json = null;
    using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
    
        json = await reader.ReadToEndAsync();
    
    //..etc

【讨论】:

【参考方案3】:

您应该使用FromBodyAttribute 进行正确映射。

【讨论】:

谢谢,我赞成这个,但我发现不只是这个问题

以上是关于ASP.NET Core 3.1 Web Api HttpPost Action 参数无法接收 axios application/json HttpPost 传递数据的主要内容,如果未能解决你的问题,请参考以下文章