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>
Von Antwort in dieser Frage: So erhalten Sie Json Post-Werte mit asp.net webapi
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
}
Lesen Sie einfach wie Request.RequestUri.ParseQueryString()[key]
public async Task Post() {
dynamic obj = await Request.Content.ReadAsAsync<JObject>();
var y = obj.var1;
}
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.
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!
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;
}
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
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);
}
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"];
}
Versuche dies.
public string Post(FormDataCollection form) {
string par1 = form.Get("par1");
// ...
}
Es funktioniert für mich mit Web-API 2
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