56

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

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

8 回答 8

70

从这个问题的答案How to get Json Post Values with asp.net webapi

  1. 使用参数绑定自动解析;请注意,dynamic由 组成JToken,因此是.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...
    }
    

警告 - 需要媒体类型application/json才能触发JsonMediaTypeFormatter处理。

于 2013-09-27T14:10:26.647 回答
22

今天花了很多时间试图围绕处理 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;
     }

希望这可以帮助!

于 2014-10-15T22:57:00.503 回答
13

我在发送带有多个参数的请求时遇到问题。

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

<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;
}
于 2013-11-13T14:22:24.290 回答
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

于 2014-06-10T16:07:31.137 回答
6

尝试这个。

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

    // ...
}

它适用于 webapi 2

于 2017-12-21T03:17:24.793 回答
4

这里没有一个答案对我有用。在 post 方法中使用 FormDataCollection 似乎是正确的答案,但是关于我的 post 请求的某些内容导致 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
于 2019-02-28T17:36:33.593 回答
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);
        }
于 2014-08-12T18:30:08.057 回答
2

有没有办法在 Web Api 控制器中处理表单发布数据?

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

public void Post(NameValueCollection formData)
{
  var value = formData["key"];
}
于 2016-10-11T08:51:41.623 回答