web-dev-qa-db-fra.com

Comment avoir POST données dans l'API Web?

J'envoie une demande au serveur sous la forme suivante:

http://localhost:12345/api/controller/par1/par2

La demande est correctement résolue avec une méthode telle que:

[HttpPost]
public void object Post(string par1, string par2)

Cependant, je transmets des données supplémentaires via le contenu de la demande. Comment puis-je récupérer ces données?

Par exemple, supposons que la demande soit envoyée à partir du formulaire:

<form action="http://localhost:12345/api/controller/par1/par2" method="post">
    <input type="hidden" name="data" value="value" />
    <input type="submit" name="submit" value="Submit" />
</form>
44
Spook

De réponse dans cette question: Comment obtenir les valeurs Json Post avec asp.net webapi

  1. Autoparse en utilisant la liaison de paramètres; notez que la dynamic est composée de JToken, d’où l’accesseur .Value.

    public void Post([FromBody]dynamic value) {
        var x = value.var1.Value; // JToken
    }
    
  2. Lire comme Request.RequestUri.ParseQueryString()[key]

    public async Task Post() {        
       dynamic obj = await Request.Content.ReadAsAsync<JObject>();
       var y = obj.var1;
    }
    
  3. Identique à # 2, mais pas de manière asynchrone (?) Afin que vous puissiez l'utiliser dans une méthode d'assistance

    private T GetPostParam<T>(string key) {
        var p = Request.Content.ReadAsAsync<JObject>();
        return (T)Convert.ChangeType(p.Result[key], typeof(T)); // example conversion, could be null...
    }
    

Avertissement - attend le type de média application/json afin de déclencher le traitement de JsonMediaTypeFormatter.

64
drzaus

Après avoir passé un bon bout de temps aujourd'hui à essayer de comprendre le changement de paradigme (important mais puissant) entre les anciennes méthodes de traitement des données de formulaire Web et la procédure utilisée avec WebAPI, j'ai pensé ajouter mes 2 centimes à cette discussion .

Ce que je voulais faire (ce qui est assez courant pour le traitement de formulaire Web d'un message POST) est de pouvoir saisir toutes les valeurs de formulaire que je veux, dans n'importe quel ordre. Dites ce que vous pouvez faire si vos données sont dans un System.Collections.Specialized.NameValueCollection. Cependant, dans WebAPI, les données d'un POST vous sont transmises sous forme de flux. Donc, vous ne pouvez pas le faire directement.

Mais il existe une petite classe sympa nommée FormDataCollection (dans System.Net.Http.Formatting) et elle vous permettra de parcourir une fois votre collection.

J'ai donc écrit une méthode utilitaire simple qui va parcourir FormDataCollection une fois et coller toutes les valeurs dans un NameValueCollection. Une fois que cela est fait, vous pouvez parcourir les données à votre guise.

Donc, dans ma classe dérivée ApiController, j'ai une méthode de publication comme celle-ci:

    public void Post(FormDataCollection formData)
    {
        NameValueCollection valueMap = WebAPIUtils.Convert(formData);

        ... my code that uses the data in the NameValueCollection
    }

La méthode Convert dans ma classe statique WebAPIUtils ressemble à ceci:

    /// <summary>
    /// Copy the values contained in the given FormDataCollection into 
    /// a NameValueCollection instance.
    /// </summary>
    /// <param name="formDataCollection">The FormDataCollection instance. (required, but can be empty)</param>
    /// <returns>The NameValueCollection. Never returned null, but may be empty.</returns>
    public static NameValueCollection Convert(FormDataCollection formDataCollection)
    {
        Validate.IsNotNull("formDataCollection", formDataCollection);

        IEnumerator<KeyValuePair<string, string>> pairs = formDataCollection.GetEnumerator();

        NameValueCollection collection = new NameValueCollection();

        while (pairs.MoveNext())
        {
            KeyValuePair<string, string> pair = pairs.Current;

            collection.Add(pair.Key, pair.Value);
        }

        return collection;
     }

J'espère que cela t'aides!

19
Brad

J'ai eu un problème avec l'envoi d'une demande avec plusieurs paramètres.

Je l'ai résolu en envoyant une classe, avec les anciens paramètres comme propriétés.

<form action="http://localhost:12345/api/controller/method" method="post">
    <input type="hidden" name="name1" value="value1" />
    <input type="hidden" name="name2" value="value2" />
    <input type="submit" name="submit" value="Submit" />
</form>

Classe de modèle:

public class Model {
    public string Name1 { get; set; }
    public string Name2 { get; set; }
}

Manette:

public void method(Model m) {
    string name = m.Name1;
}
10
Corné Strijkert

Il est difficile de gérer plusieurs paramètres directement sur l'action. La meilleure façon de le faire est de créer une classe de modèle de vue. Ensuite, vous avez un paramètre unique, mais le paramètre contient plusieurs propriétés de données.

public class MyParameters
{
    public string a { get; set; } 
    public string b { get; set; }
}

public MyController : ApiController
{
    public HttpResponseMessage Get([FromUri] MyParameters parameters) { ... }
}

Ensuite vous allez à:

http://localhost:12345/api/MyController?a=par1&b=par2

Référence: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

Si vous souhaitez utiliser "/ par1/par2", vous pouvez enregistrer une règle de routage asp. par exemple, routeTemplate: "API/{contrôleur}/{action}/{a}/{b}".

Voir http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

9
Curtis Yallop

J'ai trouvé que, dans mon cas d'utilisation, c'était beaucoup plus utile. J'espère que cela aidera quelqu'un d'autre qui a passé du temps à répondre à cette question en l'appliquant

public IDictionary<string, object> GetBodyPropsList()
        {
            var contentType = Request.Content.Headers.ContentType.MediaType;
            var requestParams = Request.Content.ReadAsStringAsync().Result;

            if (contentType == "application/json")
            {
                return Newtonsoft.Json.JsonConvert.DeserializeObject<IDictionary<string, object>>(requestParams);
            }
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }
3
Maslow

Est-il possible de gérer les données de publication de formulaire dans un contrôleur Web Api?

L'approche normale dans l'API Web ASP.NET consiste à représenter le formulaire en tant que modèle afin que le formateur de type de support le désérialise. Une alternative consiste à définir le paramètre des actions comme NameValueCollection:

public void Post(NameValueCollection formData)
{
  var value = formData["key"];
}
2
GreyCloud

Essaye ça.

public string Post(FormDataCollection form) {
    string par1 = form.Get("par1");

    // ...
}

Cela fonctionne pour moi avec Web Api 2

1
Antonio Santise

Aucune des réponses ici n'a fonctionné pour moi. Utiliser FormDataCollection dans la méthode de publication semble être la bonne réponse, mais quelque chose dans ma demande de publication a provoqué l’étouffement de webapi. finalement, je l'ai fait fonctionner en n'incluant aucun paramètre dans l'appel de méthode et en analysant simplement manuellement les paramètres de formulaire comme celui-ci.

public HttpResponseMessage FileUpload() {
    System.Web.HttpRequest httpRequest = System.Web.HttpContext.Current.Request;
    System.Collections.Specialized.NameValueCollection formData = httpRequest.Form;
    int ID = Convert.ToInt32(formData["ID"]);
    etc
0
nuander