如何在Web API中获取POST数据?

时间:2013-07-24 11:32:26

标签: asp.net asp.net-web-api

我正在以下列形式向服务器发送请求:

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>

8 个答案:

答案 0 :(得分:64)

在这个问题中来自answerHow to get Json Post Values with asp.net webapi

  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...
    }
    
  4. 警告 - 期望媒体类型application/json以便触发JsonMediaTypeFormatter处理。

答案 1 :(得分:20)

今天花了很多时间试图围绕处理Web表单数据的旧方式与WebAPI处理之间的(重要但强大的)范式转换,我想我会加上我的2美分讨论。

我想要做的事情(对于POST的Web表单处理来说很常见)是能够以任何顺序获取我想要的任何表单值。如果您的数据位于System.Collections.Specialized.NameValueCollection,就可以这样说。但事实证明,在WebAPI中,来自POST的数据会以流形式返回给您。所以你不能直接这样做。

但是有一个名为FormDataCollection的很酷的小类(在System.Net.Http.Formatting中),它让你做的是迭代你的集合一次。

所以我编写了一个简单的实用工具方法,它将遍历FormDataCollection一次并将所有值都粘贴到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;
     }

希望这有帮助!

答案 2 :(得分:10)

发送带有多个参数的请求时出现问题。

我通过发送一个类来解决它,将旧参数作为属性。

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

答案 3 :(得分:9)

直接处理动作的多个参数很困难。更好的方法是创建一个视图模型类。然后你有一个参数,但参数包含多个数据属性。

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

答案 4 :(得分:3)

我发现我的用例更有用,希望它可以帮助其他人花时间在这个答案上应用它

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

答案 5 :(得分:2)

Is there a way to handle form post data in a Web Api controller?

ASP.NET Web API中的常规方法是将表单表示为模型,以便媒体类型格式化程序对其进行反序列化。另一种方法是将动作的参数定义为NameValueCollection:

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

答案 6 :(得分:2)

这里没有答案对我有用。在post方法中使用FormDataCollection似乎是正确的答案,但是关于我的post请求的某些原因导致webapi阻塞。最终,我通过在方法调用中不包含任何参数,而只是手动解析出这样的表单参数来使它起作用。

{{1}}

答案 7 :(得分:1)

试试这个。

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

    // ...
}

它适用于webapi 2