webentwicklung-frage-antwort-db.com.de

ASP.NET Core API POST Parameter ist immer null

Ich habe folgendes gelesen:

Mein Endpunkt:

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

Meine Anfrage:

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

Dabei ist cookie die Zeichenfolge, die ich von der Benutzereingabe sende.

Die Anforderung wird mit den entsprechenden Daten an den Endpunkt gesendet. Mein String ist jedoch immer null. Ich habe versucht, das [FromBody]-Tag zu entfernen und vor den geposteten Daten einen = ohne Erfolg hinzuzufügen. Ich habe auch versucht, verschiedene Inhaltstypen mit allen oben genannten Kombinationen hinzuzufügen und zu entfernen.

Der Grund, warum ich diese spezifische Aktion mache, ist lang und spielt für diese Frage keine Rolle.

Warum ist mein Parameter immer null, egal was ich zu tun scheine?

Edit: Ich habe auch versucht, {cookie: cookie} zu verwenden.

Edit2: Die Anfrage:

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

Antwortheader

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?=

Anforderungsheader

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

Nutzlast anfordern

=sec_session_id=[redacted]; _ga=[redacted]; AWSELB=[redacted]
19
Douglas Gaskell

Das Problem ist, dass der Content-Typeapplication/json ist, während die Anforderungsnutzdaten tatsächlich text/plain sind. Dies führt zu einem 415 HTTP-Fehler, der nicht unterstützt wird. 

Sie haben mindestens zwei Optionen zum Ausrichten von Content-Type und dem tatsächlichen Inhalt.

Verwenden Sie application/json

Behalten Sie Content-Type als application/json bei, und stellen Sie sicher, dass die Anforderungsnutzdaten gültiger JSON sind. Nehmen Sie zum Beispiel Ihre Anfrage-Payload folgendermaßen vor: 

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

Dann muss die Aktionssignatur ein Objekt mit der gleichen Form wie das JSON-Objekt akzeptieren.

public class CookieWrapper
{
    public string Cookie { get; set; }
}

Anstelle der CookieWrapper-Klasse können Sie auch dynamic oder Dictionary<string, string> akzeptieren und auf den Endpunkt wie cookie["cookie"] zugreifen

public IActionResult GetRankings([FromBody] CookieWrapper cookie)

public IActionResult GetRankings([FromBody] dynamic cookie)

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

Verwenden Sie Text/Plain

Die andere Alternative besteht darin, Ihren Content-Type in text/plain zu ändern und Ihrem Projekt einen Klartext-Eingabeformatierer hinzuzufügen. Erstellen Sie dazu die folgende Klasse. 

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

Und konfigurieren Sie Mvc, um es zu verwenden. 

services.AddMvc(options =>
{
    options.InputFormatters.Add(new TextPlainInputFormatter());
});

Siehe auch

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

32
Shaun Luttin

Shaun Luttins Antwort funktioniert, aber es fehlt eine wichtige Information. Der Grund dafür, dass Ihre Zeichenfolge nicht erkannt wird, ist, dass es sich nicht um eineJSONZeichenfolge handelt.

Mach das;

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

Dann können Sie den Controller so lassen, wie er ist.

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

Es ist peinlich, wie lange ich brauchte, um das herauszufinden. Ich hoffe wirklich, dass es jemandem hilft!

7
statler

Sie müssen lediglich den Körper in Anführungszeichen setzen, sodass er eine string darstellt. Sie müssen den Anfragetyp auch als application/json belassen. Auf diese Weise wird der Medientyp-Formatierer es herausfinden:

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

Sollte den Trick tun.

1
Haney

lächerlich..... in dot net core können Sie nicht einfach "frombody string parameter" . verwenden. Sie sollten eine Modellklasse für nur einen string-Parameter erstellen.

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)
1
guhyeon

Ich hatte viel zu lange damit zu kämpfen, und nachdem ich mir angesehen hatte, was ein DevExpress-Steuerelement für das "PUT" -Aufrufen einer Rasiermesserseite tat, entdeckte ich dieses Nugget:

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 
}

Der Trick besteht darin, den "application/x-www-form-urlencoded; charset = UTF-8" als Inhaltstyp für die Anforderung zu verwenden. Auf diese Weise müssen Sie keine Klasse für einen einzelnen Zeichenfolgenwert erstellen. Und die Dinge funktionieren wie erwartet.

0
Danno

Ich musste String-Daten vom .NET Desktop-Client an den .NET Core Host senden. Ich habe einen nicht unterstützten Medienfehler erhalten. Ich bin Shaun Luttins Antwort gefolgt und habe gut funktioniert. Ich fand etwas einfacher, um nur String-Daten als folge zu erhalten, falls jemand anderes nützlich ist:

[HttpPost]
[Route("Request/Echo")]
public async Task<string> Echo()
{
    using (var Reader = new StreamReader(Request.Body, Encoding.UTF8))
    {
        return await Reader.ReadToEndAsync();
    }
}

Dieser Beitrag ist sehr nützlich.

0
Demir