webentwicklung-frage-antwort-db.com.de

Wie kommt man POST Daten in Web-API?

Ich sende eine Anfrage in folgender Form an den Server:

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

Die Anfrage wird korrekt in eine Methode wie folgt aufgelöst:

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

Ich leite jedoch zusätzliche Daten durch den Anforderungsinhalt. Wie kann ich diese Daten abrufen?

Nehmen wir zum Beispiel an, dass die Anfrage aus dem Formular gesendet wird:

<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

Von Antwort in dieser Frage: So erhalten Sie Json Post-Werte mit asp.net webapi

  1. Autoparse über Parameterbindung; Beachten Sie, dass die dynamic aus JToken besteht, daher der .Value-Accessor.

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

    public async Task Post() {        
       dynamic obj = await Request.Content.ReadAsAsync<JObject>();
       var y = obj.var1;
    }
    
  3. Wie # 2, nur nicht asynchron (?), Sodass Sie es in einer Hilfsmethode verwenden können

    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...
    }
    

Warnung - erwartet Medientyp application/json, um die JsonMediaTypeFormatter-Behandlung auszulösen.

64
drzaus

Nachdem ich heute viel Zeit mit dem Versuch verbracht hatte, meinen Kopf um den (signifikanten, aber mächtigen) Paradigmenwechsel zwischen den alten Verfahren zur Verarbeitung von Webformulardaten und der Vorgehensweise bei der WebAPI zu wickeln, dachte ich, ich würde dieser Diskussion meine 2 Cent hinzufügen .

Was ich tun wollte (was für die Verarbeitung von POST-Formularen im Web recht üblich ist), ist in der Lage zu sein, die gewünschten Formwerte in beliebiger Reihenfolge abzurufen. Sagen Sie, wie Sie es tun können, wenn Sie Ihre Daten in einem System.Collections.Specialized.NameValueCollection haben. Es stellt sich jedoch heraus, dass in WebAPI die Daten eines POST als Stream auf Sie zurückkommen. Das kannst du also nicht direkt machen.

Es gibt jedoch eine coole kleine Klasse mit dem Namen FormDataCollection (in System.Net.Http.Formatting), und Sie können dies tun, indem Sie Ihre Sammlung einmal durchlaufen.

Also habe ich eine einfache Utility-Methode geschrieben, die einmal die FormDataCollection durchläuft und alle Werte in eine NameValueCollection steckt. Sobald dies geschehen ist, können Sie die Daten nach Herzenslust überspringen.

In meiner abgeleiteten ApiController-Klasse habe ich eine Post-Methode wie diese:

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

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

Die Convert-Methode in meiner statischen WebAPIUtils-Klasse sieht folgendermaßen aus:

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

Hoffe das hilft!

19
Brad

Ich hatte ein Problem mit dem Senden einer Anfrage mit mehreren Parametern.

Ich habe es gelöst, indem ich eine Klasse mit den alten Parametern als Eigenschaften sendete.

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

Modellklasse:

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

Regler:

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

Es ist schwierig, mehrere Parameter für die Aktion direkt zu behandeln. Am besten erstellen Sie eine Ansichtsmodellklasse. Dann haben Sie einen einzelnen Parameter, der Parameter enthält jedoch mehrere Dateneigenschaften.

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

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

Dann gehst du zu:

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

Referenz: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

Wenn Sie "/ par1/par2" verwenden möchten, können Sie eine Asp-Routing-Regel registrieren. zB routeTemplate: "API/{Controller}/{Aktion}/{a}/{b}" ".

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

9
Curtis Yallop

Ich fand, dass dies für meinen Anwendungsfall viel nützlicher war, hoffentlich hilft es jemand anderem, der Zeit damit verbracht hat, diese Antwort anzuwenden

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

Gibt es eine Möglichkeit, mit Post-Post-Daten in einem Web-Api-Controller umzugehen?

Die normale Vorgehensweise in ASP.NET-Web-API besteht darin, das Formular als Modell darzustellen, sodass der Medientyp-Formatierer es deserialisiert. Alternativ können Sie den Parameter der Aktionen als NameValueCollection definieren:

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

Versuche dies.

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

    // ...
}

Es funktioniert für mich mit Web-API 2

1
Antonio Santise

Keine der Antworten funktionierte für mich. Die Verwendung von FormDataCollection in der Post-Methode scheint die richtige Antwort zu sein, aber etwas über meine Post-Anfrage hat dazu geführt, dass Webapi verschluckt wurde. Irgendwann habe ich es geschafft, indem ich keine Parameter in den Methodenaufruf einfügte und die Formularparameter einfach manuell analysiert.

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