web-dev-qa-db-fra.com

"400/L'entrée n'était pas valide" lors de l'appel de l'API Web principale ASP.NET

Je teste mon API Web en utilisant postman et je récupère une "400 requête incorrecte" ou un "" L'entrée n'était pas valide "dans Postman. Le point de rupture sur la première ligne de mon action n'est pas touché. Comment puis-je comprendre ce qui se passe dans les coulisses?

Je montrerais une capture d'écran de Postman, mais je ne parviens pas à télécharger l'image. C'est simplement un POST avec plusieurs champs spécifiés pour le corps. Voici l'URL:

http://localhost:52126/api/v1/itinerary

Voici l'action:

[HttpPost]
[Route("api/v1/itinerary")]
public async Task<ActionResult> AddItineraryAsync([FromBody] Itinerary itinerary)
{
    if (!ModelState.IsValid) // Break point on this line not getting hit!
    {
        return BadRequest(ModelState);
    }

    await Logic.AddItineraryAsync(itinerary);

    return Ok();
}

À l'origine, je n'avais pas spécifié [FromBody] pour l'action. Cela ne fonctionne pas de toute façon. Que puis-je vérifier pour savoir ce qui se passe?

Clarification (en réponse à Chris Pratt):

Je suis à mes débuts dans l'écriture de ma première application mobile et, étant un type du bas vers le haut, certains appels d'API Web fonctionnent. Je suppose que je vais transmettre le code JSON de l'application mobile à cette couche de serveur.

Je n'ai rien fait avec les jetons anti-falsification dans ce projet d'API Web, donc je suppose qu'ils ne sont pas en jeu ... à moins que ce ne soit quelque chose qui vienne de Postman.

La suppression du paramètre de l'action ne permet à l'exécution de tomber jusqu'à mon point d'arrêt. L'erreur semble donc être liée à la tentative de liaison d'ASP.NET.

Après avoir fouillé un peu dans Postman, j'ai constaté que l'en-tête spécifiait x-www-form-urlencoded pour le type de contenu. Je l'ai changé en application/json, comme vous l'avez suggéré. Cependant, cela n'a pas semblé faire la différence.

Plus d'informations:

Après avoir essayé ce que Carl a suggéré ci-dessous, j'ai plus d'informations. L'exécution est tombée dans l'action et j'ai jeté un œil à ce qui est transmis par Postman. C'est ici:

----------------------------179455694862693501539465
Content-Disposition: form-data; name="StartPoint"

Tacoma
----------------------------179455694862693501539465
Content-Disposition: form-data; name="EndPoint"

Portland
----------------------------179455694862693501539465
Content-Disposition: form-data; name="TravelDate"

2018-8-21 07:00:00 AM
----------------------------179455694862693501539465
Content-Disposition: form-data; name="Name"

Test Itinerary
----------------------------179455694862693501539465
Content-Disposition: form-data; name="UserAccountId"

2
----------------------------179455694862693501539465
Content-Disposition: form-data; name="Comment"

Just doin' some testing.
----------------------------179455694862693501539465--

La désérialisation Json échoue avec:

JsonReaderException: Input string &#x27;----------------------------179455694862693501539465&#x27; is not a valid number.

Quels sont ces chiffres et d'où viennent-ils?

2
birdus

ModelState n'est validé que s'il est capable de désérialiser correctement le post body/bind.

Vous n’êtes pas précis dans votre question, mais il semble que vous publiez en tant que x-www-form-urlencoded. Si c'est le cas, vous devriez pas avoir [FromBody]. Cependant, gardez à l'esprit qu'il s'agit d'un cas de figure, donc si vous souhaitez publier ultérieurement via JSON, vous devez conserver l'attribut et publier JSON à partir de Postman.

En plus de cela, assurez-vous que vous n'utilisez pas la validation de jeton antiforgery ou que vous publiez un jeton valide avec la demande. L'échec de la validation de l'antiforgerie court-circuitera la demande et renverra un 400 immédiatement.

Si vous publiez du JSON, assurez-vous que votre JSON est valide. Si le JSON n'est pas valide, vous recevrez immédiatement un 400.

3
Chris Pratt

Je l'essayais comme votre [FromBody] Itinerary itinerary mais j'ai trouvé un moyen de contourner le problème. La structure 2.1 contient Problèmes https://github.com/aspnet/Mvc/issues/7609 et https://github.com/aspnet/Mvc/issues/7799 . Je travaille dans la version 2.1: le javascript du client est inchangé:

var payload = JSON.stringify({ "name": document.getElementById('firstname').value, "email": document.getElementById('email').value, "captcha": grecaptcha.getResponse() });
var oReq = new XMLHttpRequest();
oReq.ContentType = "application/json";

oReq.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {

        document.getElementById("update").innerHTML = this.responseText;
    }
    else document.getElementById("update").innerHTML = "not 4&200! : " + this.responseText;
};

oReq.open('POST', 'api/u');
oReq.send(payload);

et le contrôleur a:

[Route("api/[controller]")]
//  [ApiController] // works either way
public class UController : ControllerBase
{
    [HttpPost]
    public async Task<string> signUp()
    {
        String body;
        using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
        {
            body = await reader.ReadToEndAsync();
        }

        UserSignup user = JsonConvert.DeserializeObject<UserSignup>(body);

        return user.email;
    }
}

Bientôt sur https://github.com/Hover-Us/

1
Carl Cook

Solution du commentaire: 

Pour 179455694862693501539465, il semble que vous utilisez PostMan avec application/x-www-form-urlencoded as Content-Type.
Je vous suggère de suivre les étapes suivantes:
1. gardez votre api avec AddItineraryAsync ([itinéraire de l'itinéraire FromBody]);
2. effacer vos en-têtes dans postier
3. Onglet Body choisissez raw avec JSON (application/json)
4. entrez une chaîne JSON valide ou simplement avec {}
5. assurez-vous qu'il n'y a pas d'en-têtes supplémentaires, à l'exception de application/json en tant que contenu-type dans l'onglet en-têtes.
6. envoyer une demande pour vérifier si la méthode api sera touchée.

0
Tao Zhou