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

时间:2017-01-23 03:21:55

标签: c# ajax asp.net-web-api asp.net-core

我已阅读以下内容:

我的终点:

[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是我从用户输入发送的字符串。

请求使用适当的数据发布到端点。但是,我的字符串始终为null。我尝试删除[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]

9 个答案:

答案 0 :(得分:35)

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

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

使用application / 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<string, string>,并在端点中像cookie["cookie"]那样访问它

public IActionResult GetRankings([FromBody] CookieWrapper cookie)

public IActionResult GetRankings([FromBody] dynamic cookie)

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

使用text / plain

另一种方法是将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

答案 1 :(得分:7)

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
});

这让我想出多长时间才尴尬。我真的希望它有所帮助!

答案 2 :(得分:2)

荒谬的是 在点网核心中,您不能仅使用“ 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)

答案 3 :(得分:1)

您只需将正文放在引号中,使其代表string。您还需要将请求类型保留为application/json。这样媒体类型格式化器就可以解决这个问题:

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

应该做的伎俩。

答案 4 :(得分:1)

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

愿这节省了别人的时间。

答案 5 :(得分:0)

我需要通过.Net Desktop Client将字符串数据发布到.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 :(得分:0)

我为此苦苦挣扎了很长时间,最后,在查看DevExpress控件为将“ PUT”设置到Razor Page所做的工作之后,我发现了这个块:

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 :(得分:0)

我的特别问题是,对于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 :(得分:0)

就我而言,我像@guhyeon建议的那样进行了设置,其中的模型类仅包含字符串属性。除了没有被定义为属性,它只是

public class PdfInfoRequestDto
{
    public string PdfInBase64;
}

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

public string PdfInBase64 { get; set; }

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