ASP.NET Core API POST 参数始终为空

Posted

技术标签:

【中文标题】ASP.NET Core API POST 参数始终为空【英文标题】:ASP.NET Core API POST parameter is always null 【发布时间】:2017-06-07 12:25:59 【问题描述】:

我已阅读以下内容:

Asp.net Core Post parameter is always null asp.net webapi 2 post parameter is always null web-api POST body object always null Web Api Parameter always null

我的端点:

[HttpPost]
[Route("/getter/validatecookie")]
public async Task<IActionResult> GetRankings([FromBody] string cookie)

    int world = 5;
    ApiGetter getter = new ApiGetter(_config, cookie);
    if (!await IsValidCookie(getter, world))
    
        return BadRequest("Invalid CotG Session");
    
    HttpContext.Session.SetString("cotgCookie", cookie);
    return Ok();

我的要求:

$http.post(ENDPOINTS["Validate Cookie"],  cookie , 'Content-Type': 'application/json');

cookie 是我从用户输入发送的字符串。

请求使用适当的数据发布到端点。但是,我的字符串始终为空。我尝试删除[FromBody] 标签,并在发布的数据前添加=,但没有成功。我还尝试使用上述所有组合添加和删除不同的内容类型。

我做这个具体动作的原因很长,和这个问题无关。

为什么无论我做什么,我的参数总是为空?

编辑:我也尝试过使用cookie: cookie

Edit2:请求:

Request URL:http://localhost:54093/getter/validatecookie
Request Method:POST
Status Code:400 Bad Request
Remote Address:[::1]:54093

响应标头

Content-Type:text/plain; charset=utf-8
Date:Mon, 23 Jan 2017 03:12:54 GMT
Server:Kestrel
Transfer-Encoding:chunked
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?QzpcVXNlcnNcRG91Z2xhc2cxNGJcRG9jdW1lbnRzXFByb2dyYW1taW5nXENvdEdcQ290RyBBcHBcc3JjXENvdEdcZ2V0dGVyXHZhbGlkYXRlY29va2ll?=

请求标头

POST /getter/validatecookie HTTP/1.1
Host: localhost:54093
Connection: keep-alive
Content-Length: 221
Accept: application/json, text/plain, */*
Origin: http://localhost:54093
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Content-Type: application/json;charset=UTF-8
Referer: http://localhost:54093/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8

请求负载

=sec_session_id=[redacted]; _ga=[redacted]; AWSELB=[redacted]

【问题讨论】:

您是否使用过 Fiddler 或浏览器的网络控制台等工具来确保 POST 正确发送正文? @ShaunLuttin 是的,我提到它确实发布了适当的数据。数据在请求中发送。 您可以发布实际的 HTTP 请求及其标头和正文,而不是发布您如何发出 AJAX 请求。这可能有助于解决问题。 @ShaunLuttin 我已经在里面添加了请求 您的请求负载不是 JSON,而您的 Content-Type 是 application/json。 【参考方案1】:

问题在于Content-Typeapplication/json,而请求负载实际上是text/plain。这将导致 415 Unsupported Media Type HTTP 错误。

您至少有两个选项可以对齐Content-Type 和实际内容。

使用应用程序/json

Content-Type 保留为application/json,并确保请求有效负载是有效的 JSON。例如,使您的请求有效负载:


    "cookie": "=sec_session_id=[redacted]; _ga=[redacted]; AWSELB=[redacted]"
 

那么动作签名需要接受一个与JSON对象形状相同的对象。

public class CookieWrapper

    public string Cookie  get; set; 

而不是 CookieWrapper 类,或者您可以接受动态,或 Dictionary&lt;string, string&gt; 并像端点中的 cookie["cookie"] 一样访问它

public IActionResult GetRankings([FromBody] CookieWrapper cookie)

public IActionResult GetRankings([FromBody] dynamic cookie)

public IActionResult GetRankings([FromBody] Dictionary<string, string> cookie)

使用文本/纯文本

另一种选择是将您的Content-Type 更改为text/plain 并将纯文本输入格式化程序添加到您的项目中。为此,请创建以下类。

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 = context.ReaderFactory(
            context.HttpContext.Request.Body, 
            encoding))
        
            data = await streamReader.ReadToEndAsync();
        

        return InputFormatterResult.Success(data);
    

并配置 Mvc 来使用它。

services.AddMvc(options =>

    options.InputFormatters.Add(new TextPlainInputFormatter());
);

另见

https://github.com/aspnet/Mvc/issues/5137

【讨论】:

感谢回复,刚刚试过,同样的交易。 ASP.NET 参数是否不像其他框架那样接受数据? 知道了... ASP.NET Core 不支持将text/plain 作为开箱即用的Content-Type Shaun,我最终将Dictionary&lt;string,string&gt;"cookie":cookie 对象一起使用。然后我在我的端点中像cookie["cookie"] 一样访问它。如果您可以将其添加为潜在的解决方案之一,我将接受您的回答。 这不应该是答案。您可以在 .Net Core 中非常轻松地发送字符串,而无需所有这些棘手的操作。请参阅下面的答案 您可以看到他是从Microsoft.AspNetCore.Mvc.Formatters 中的TextInputFormatter 派生的。然而,这是一个抽象类,此时唯一的派生类是 JSON 和 XML。也就是说,我真的希望 TextPlainInputFormatter 被包括在内。非常感谢,肖恩!【参考方案2】:

您只需将正文放在引号中,使其代表string。您还需要将请求类型保留为application/json。这样媒体类型格式化程序就会弄清楚:

"=sec_session_id=[redacted]; _ga=[redacted]; AWSELB=[redacted]"

应该做的伎俩。

【讨论】:

变量cookie已经是一个字符串,它作为字符串在JS中传递。 对,但是请求负载也需要用双引号字符封装,以便媒体类型格式化程序正确处理[FromBody] 属性。【参考方案3】:

Shaun Luttin 的回答有效,但它遗漏了一条重要信息。无法识别您的字符串的原因是它不是 JSON 字符串。

这样做;

var payload=JSON.stringify("=sec_session_id=[redacted]; _ga=[redacted]; AWSELB=[redacted]");

然后你可以让控制器保持原样;

$.ajax(
    url: http://localhost:54093/getter/validatecookie,
    type: 'POST',
    contentType: 'application/json',
    data: payload
);

令人尴尬的是,我花了多长时间才弄清楚。我真的希望它可以帮助别人!

【讨论】:

工作。使用 axios 发布 payload【参考方案4】:

可笑的是, 在 dot net core 中,您不能只使用“frombody 字符串参数”。 你应该为一个字符串参数创建一个模型类。

public async Task<IActionResult> GetRankings([FromBody] string cookie)

=>

//1. make a model. MyCookie.cs
class MyCookie
   public string Cookie  get; set; 

//2. edit your parameter
public async Task<IActionResult> GetRankings([FromBody] MyCookie cookie)

【讨论】:

【参考方案5】:

我需要通过 .Net 桌面客户端将字符串数据发布到 .NET Core 主机。我收到不支持的媒体错误。我遵循了 Shaun Luttin 的回答并且工作正常。我发现了一些更容易获取字符串数据的方法,以防其他人发现有用:

[HttpPost]
[Route("Request/Echo")]
public async Task<string> Echo()

    using (var Reader = new StreamReader(Request.Body, Encoding.UTF8))
    
        return await Reader.ReadToEndAsync();
    

This post 很有用。

【讨论】:

【参考方案6】:

我为此苦苦挣扎了很久,最后,在查看了 DevExpress 控件为“PUT”到 Razor 页面所做的工作之后,我发现了这个问题:

javascript

$.ajax(
        type: "PUT",
        url: "/GoalGrid?handler=Single",
        dataType: "json",
        contentType: "application/x-www-form-urlencoded; charset=UTF-8",
        data: values: single 
    )

GoalGrid.cshtml.cs

public JsonResult OnPutSingle(string values)
 
     // Do stuff with 'values' here 

诀窍是使用“application/x-www-form-urlencoded; charset=UTF-8”作为请求的 contentType。这样您就不需要为单个字符串值创建一个类。一切都按预期进行。

【讨论】:

【参考方案7】:

我的特殊问题是模型绑定对于 JSON 模型静默失败。 (它始终为空)。

由于我发布了确切的 JSON,我能够通过在本地运行 Web 服务在本地调试它,并通过 cURL 发布到我的控制器(可以使用 POSTMAN)。

使用下面的代码,我能够看到序列化过程中发生的确切异常。

    [HttpPost]
    public IActionResult MyAction([FromBody] dynamic request)
                
        if (request != null)
        
            try
            
                var objAttempt =
                    JsonConvert.DeserializeObject<MyModel>(
                        JsonConvert.SerializeObject(request));
            
            catch (Exception exception)
            
                Console.WriteLine(exception);
                throw;
            
        

【讨论】:

【参考方案8】:

对我来说,只需将[FromBody] 添加到参数列表即可解决问题。

希望这可以节省别人的时间。

【讨论】:

【参考方案9】:

就我而言,我按照@guhyeon 的建议进行了设置,模型类只包含一个字符串属性。除了,它没有被定义为属性,它只是

public class PdfInfoRequestDto

    public string PdfInBase64;

由于某种原因,这适用于 .net 框架 4.7.2 webapi,我可以从请求正文中收到我需要的值。但是当我尝试在 .net core 3.1 webapi 中使用相同的请求、模型和所有内容复制相同内容时,PdfInBase64 中的值总是以 null 的形式到达我的控制器。将字段更改为属性后:

public string PdfInBase64  get; set; 

我开始正确获取请求正文中传递的值。

【讨论】:

【参考方案10】:

在两个参数上使用 [FromForm] 为我修复了它。如:

[HttpPost]
public IActionResult Insrtmyinfo([FromForm] string firstparam, [FromForm] string secndparam)

...

【讨论】:

以上是关于ASP.NET Core API POST 参数始终为空的主要内容,如果未能解决你的问题,请参考以下文章

Asp.net Core Post 参数始终为空 [关闭]

Asp.net Core 2 API POST 对象为空?

ASP.NET Core Web API HTTP POST 在 Azure 中返回 404

详解ASP.NET Core API 的Get和Post请求使用方式

以 axios.post 形式接收 asp.net core web api 中的数组

asp.net core 3 Web API !发送 json 到 POST 动作