web-dev-qa-db-fra.com

API ASP.NET Core POST paramètre est toujours nul

J'ai lu le texte suivant:

Mon point final:

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

Ma demande:

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

cookie est la chaîne que j'envoie à partir de l'entrée de l'utilisateur.

La demande est publiée sur le noeud final avec les données appropriées. Cependant, ma chaîne est toujours nulle. J'ai essayé de supprimer la balise [FromBody], ainsi que d'ajouter un = devant les données postées sans succès. J'ai également essayé d'ajouter et de supprimer différents types de contenu avec toutes les combinaisons de celles-ci.

La raison pour laquelle je fais cette action spécifique est longue et n'a pas d'importance pour cette question.

Pourquoi mon paramètre est-il toujours nul, peu importe ce que je semble faire?

Edit: j'ai aussi essayé d'utiliser {cookie: cookie}

Edit2: La requête:

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

En-têtes de réponse

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

En-têtes de demande

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

Demande de charge utile

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

Le problème est que le Content-Type est application/json, alors que la charge de la demande est en réalité text/plain. Cela entraînera une erreur HTTP de type de support non pris en charge 415. 

Vous avez au moins deux options pour aligner ensuite Content-Type et le contenu réel.

Utilisez application/json

Conservez le Content-Type en tant que application/json et assurez-vous que le payload de la demande est un JSON valide. Par exemple, chargez votre demande comme suit: 

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

Ensuite, la signature d'action doit accepter un objet ayant la même forme que l'objet JSON.

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

Au lieu de la classe CookieWrapper, ou vous pouvez accepter dynamique, ou un Dictionary<string, string> et y accéder comme cookie["cookie"] dans le noeud final

public IActionResult GetRankings([FromBody] CookieWrapper cookie)

public IActionResult GetRankings([FromBody] dynamic cookie)

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

Utiliser du texte/uni

L’autre alternative est de changer votre Content-Type en text/plain et d’ajouter un formateur de saisie de texte en clair à votre projet. Pour ce faire, créez la classe suivante. 

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

Et configurez Mvc pour l'utiliser. 

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

Voir également

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

32
Shaun Luttin

La réponse de Shaun Luttin fonctionne, mais il manque une information importante. La raison pour laquelle votre chaîne n'est pas reconnue est qu'il ne s'agit pas d'une chaîneJSON.

Faire ceci;

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

Ensuite, vous pouvez laisser le contrôleur tel quel;

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

C'est embarrassant combien de temps cela m'a pris pour comprendre. J'espère vraiment que ça aide quelqu'un!

7
statler

Vous devez simplement mettre le corps entre guillemets pour qu’il représente un string. Vous devez également laisser le type de demande application/json. De cette façon, le formateur de type de support le saura:

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

Devrait faire l'affaire.

1
Haney

ridiculement, dans le noyau de points nets, vous ne pouvez pas utiliser simplement "paramètre de chaîne frombody" ... .. vous devez créer une classe de modèle pour un seul paramètre de chaîne.

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

J'avais besoin de poster des données de chaîne par .Net Desktop Client sur .NET Core Host. Je recevais une erreur de support non prise en charge. J'ai suivi la réponse de Shaun Luttin et j'ai bien travaillé. J'ai trouvé quelque chose de plus facile pour obtenir uniquement des données de chaîne comme suit au cas où quelqu'un trouve cela utile:

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

Ce post est très utile.

0
Demir