web-dev-qa-db-ja.com

Web APIでPOSTデータを取得する方法は?

次の形式でサーバーにリクエストを送信しています。

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

要求は次のようなメソッドに正しく解決されます。

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

ただし、リクエストコンテンツを通じて追加のデータを渡します。これらのデータを取得するにはどうすればよいですか?

例のために、リクエストがフォームから送信されたとしましょう:

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

この質問の answer から: asp.net webapiでJson投稿値を取得する方法

  1. パラメータバインディングを使用した自動解析。 dynamicJTokenで構成されているため、.Valueアクセサーであることに注意してください。

    public void Post([FromBody]dynamic value) {
        var x = value.var1.Value; // JToken
    }
    
  2. Request.RequestUri.ParseQueryString()[key]のように読む

    public async Task Post() {        
       dynamic obj = await Request.Content.ReadAsAsync<JObject>();
       var y = obj.var1;
    }
    
  3. #2と同じですが、非同期(?)ではないため、ヘルパーメソッドで使用できます

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

警告-JsonMediaTypeFormatter処理をトリガーするには、メディアタイプapplication/jsonが必要です。

66
drzaus

今日は、Webフォームデータの古い処理方法とWebAPIでの処理方法との間の(重要だが強力な)パラダイムシフトに頭を悩まそうとしてかなりの時間を費やした後、この議論に2セントを追加すると思いました。 。

私がやりたかったこと(POSTのWebフォーム処理ではかなり一般的です)は、必要なフォーム値を任意の順序で取得できるようにすることです。 System.Collections.Specialized.NameValueCollectionにデータがある場合にできることを言います。ただし、WebAPIでは、POSTからのデータがストリームとして返されます。そのため、直接それを行うことはできません。

ただし、FormDataCollection(System.Net.Http.Formatting内)という名前のクールな小さなクラスがあり、これを使用すると、コレクションを1回繰り返し処理できます。

そこで、FormDataCollectionを1回実行し、すべての値をNameValueCollectionに固定する単純なユーティリティメソッドを作成しました。これが完了すると、すべてのデータを心のコンテンツにジャンプできます。

ApiController派生クラスには、次のようなpostメソッドがあります。

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

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

静的WebAPIUtilsクラスのConvertメソッドは次のようになります。

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

お役に立てれば!

20
Brad

複数のパラメーターを含むリクエストの送信で問題が発生しました。

古いパラメーターをプロパティとしてクラスを送信することで解決しました。

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

モデルクラス:

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

コントローラ:

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

アクションの複数のパラメーターを直接処理するのは困難です。より良い方法は、ビューモデルクラスを作成することです。次に、1つのパラメーターがありますが、パラメーターには複数のデータプロパティが含まれています。

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

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

次に、次の場所に移動します。

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

リファレンス: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

「/ par1/par2」を使用する場合は、aspルーティングルールを登録できます。例routeTemplate: "API/{controller}/{action}/{a}/{b}"。

http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api を参照してください

9
Curtis Yallop

私のユースケースでは、これがはるかに有用であることがわかりました。うまくいけば、この答えに時間を費やして他の人がそれを適用するのに役立つことを願っています

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

ここでの答えはどれも役に立たなかった。 postメソッドでFormDataCollectionを使用するのは正しい答えのように思えますが、私の投稿リクエストに関する何かがwebapiを停止させました。最終的には、メソッド呼び出しにパラメーターを含めず、このようなフォームパラメーターを手動で解析することで機能させました。

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

Web Apiコントローラーでフォーム送信データを処理する方法はありますか?

ASP.NET Web APIの通常のアプローチは、フォームをモデルとして表現し、メディアタイプフォーマッターがそれを逆シリアル化することです。別の方法は、アクションのパラメーターをNameValueCollectionとして定義することです。

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

これを試して。

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

    // ...
}

Web API 2で動作します

1
Antonio Santise