web-dev-qa-db-fra.com

Utiliser Fiddler pour envoyer un POST demande à Web Api

J'écris un programme WebApi simple, en C #. (Je connais assez bien MVC, mais WebApi est une nouveauté.) Il contient un contrôleur Vendors (VendorsController.cs), qui contient une action "getvendor" comme indiqué dans l'exemple de code ci-dessous:

[RoutePrefix("api/vendors")]
public class VendorsController : ApiController
{
    [Route("getvendor"), HttpPost]
    public TAPUser GetVendor([FromBody] string username)
    {
        Int32 userid = -1;

    ...

Les itinéraires sont configurés comme suit:

// Web API routes
config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { action = RouteParameter.Optional, id = RouteParameter.Optional
);

J'utilise Fiddler pour tester le programme. Tout d'abord, j'ai exécuté le code ci-dessus sans [FromBody] et utilisé Fiddler pour envoyer une demande POST avec le nom d'utilisateur dans l'URL comme ceci: http: // localhost: 60060/api/vendors/getvendor? username = tapuser

Cela a bien fonctionné. tapuser a été passé en tant qu'argument à GetVendor et l'action a renvoyé le résultat attendu.

Ensuite, j'ai ajouté [FromBody] et mis username = tapuser dans le corps de la requête. Cette fois-ci, lorsque j'ai envoyé la demande, tapuser n'est pas passé à l'action. L'argument de GetVendor () était null. J'ai essayé des variantes sur le corps de la requête, telles que {"nom d'utilisateur": "tapuser"}, mais cela n'aide pas. J'ai également essayé de modifier l'itinéraire de différentes manières, notamment en modifiant l'itinéraireTemplate en "api/{controller}/{action}/{id}". Cela n'a pas aidé non plus. Je suis sûr que quelque chose de très simple me manque, mais je ne le vois pas.

7
Tim

Essayez de placer votre valeur directement dans le corps de la demande. Regarde ça.  enter image description here

14
drunkcoder

Maintenant, j'ai fait du débogage et j'ai pu recréer le problème que vous aviez. 

J'ai finalement réussi à obtenir les données pour l'action en procédant comme suit:

Tout d'abord, j'ai créé une classe pour agir en tant que conteneur pour la charge utile.

public class body {
    public string username { get; set; }
}

et mis à jour l'action pour correspondre

[Route("getvendor"), HttpPost]
public TAPUser GetVendor([FromBody] body payload) {...}

Puis, en utilisant le violoneux, j'ai composté la demande sur le noeud final à tester.

POST  http://localhost:60060/api/vendors/getvendor HTTP/1.1
User-Agent: Fiddler
Host: localhost:60060
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Content-Length: 16

username=tapuser

Lorsque mon point de rupture a été atteint, le corps/charge a été renseigné avec le nom d'utilisateur tapuser.

METTRE À JOUR

Maintenant que tout ce qui précède fonctionnait, je n’étais pas tout à fait sûr que cela résout votre problème, alors j’ai fait quelques recherches sur Google et j’ai trouvé 

Liaison de paramètres dans l'API Web ASP.NET

Où cela a montré l'exemple suivant en utilisant [FromBody]

Pour forcer l'API Web à lire un type simple à partir du corps de la demande, ajoutez le [FromBody] attribut au paramètre:

public HttpResponseMessage Post([FromBody] string name) { ... }

Dans cet exemple, l'API Web utilisera un formateur de type média pour lire le fichier valeur du nom du corps de la demande. Voici un exemple de client demande.

POST http://localhost:5076/api/values HTTP/1.1
User-Agent: Fiddler
Host: localhost:5076
Content-Type: application/json
Content-Length: 7

"Alice"

Lorsqu'un paramètre a [FromBody], l'API Web utilise l'en-tête Content-Type pour sélectionner un formateur. Dans cet exemple, le type de contenu est "application/json" et le corps de la demande est une chaîne JSON brute (et non un objet JSON).

Au plus un paramètre est autorisé à lire dans le corps du message. Alors cela ne fonctionnera pas:

// Caution: Will not work!    
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }

La raison de cette règle est que le corps de la demande peut être stocké dans un fichier flux non tamponné qui ne peut être lu qu'une seule fois.

Lorsque j'ai annulé mes modifications initiales et suivi l'exemple, cela a fonctionné comme prévu.

J'espère que cela t'aides.

1
Nkosi

J'ai découvert que si je mettais 'tapuser' dans le corps de la demande, en utilisant des guillemets simples ou doubles, cela fonctionnerait. Les citations semblent être la réponse. Si je mets autre chose que tapuser à l'intérieur des guillemets, le tout est passé comme argument. Par exemple, '{username = tapuser}' sera passé sous la forme {username = tapuser}. Merci à tous pour votre contribution.

1
Tim