【问题标题】:ASP.NET web api cannot get application/x-www-form-urlencoded HTTP POSTASP.NET web api 无法获取 application/x-www-form-urlencoded HTTP POST
【发布时间】:2013-12-20 14:02:29
【问题描述】:

我是 web-api 的新手。我想使用 web-api 接收 HTTP POST 数据。 content-type 是application/x-www-form-urlencoded,请求体是这样的:

data={"mac":"0004ED123456","model":"SG6200NXL"}(JSON 格式)。

我的控制器是这样的:

public void Post([FromBody]string formData)
{
    data.Add(formData);
}

但 formData 始终为空。仅当我将请求正文更改为:

={"mac":"0004ED123456","model":"SG6200NXL"}

我可以找到{"mac":"0004ED123456","model":"SG6200NXL"} 保存在我的formData 字符串中。

所以我的问题是我应该如何接收格式的数据:

data={"mac":"0004ED123456","model":"SG6200NXL"}?

有没有一种简单的方法可以将 JSON 淡化为 C#?

感谢您的帮助!

更新: 我尝试使用模型,但它仍然不适合我。 我的模型是:

public class Device
    {
        public string mac { get; set; }
        public string model { get; set; }
    }

我的 HTTP POST 请求是:

标题:

User-Agent: Fiddler
Content-type: application/x-www-form-urlencoded
Host: localhost:52154
Content-Length: 46

正文:

data={"mac":"0004ED123456","model":"SG6200NX"}

据我所知,我必须使用Content-type: application/x-www-form-urlencoded,因为 HTTP POST 是由路由器发送的。我的工作是接收数据。

【问题讨论】:

    标签: c# asp.net json asp.net-web-api


    【解决方案1】:

    引用here:

    默认情况下,Web API 会尝试从请求 URI 中获取简单类型。 FromBody 属性告诉 Web API 从请求正文中读取值。

    Web API 最多读取一次响应正文,因此一个动作的一个参数只能来自请求正文。如果您需要从请求正文中获取多个值,请定义一个复杂类型。

    其次,客户端需要发送如下格式的值:

    =值

    具体来说,对于简单类型,名称/值对的名称部分必须为空。

    所以,如果要以data=string 格式发布数据,则必须创建复杂类型。

    public class MyFormData
    {
        public string Data { get; set; }
    }
    

    然后像这样更新你的控制器:

    public void Post(MyFormData formData)
    {
        //your JSON string will be in formData.Data
    }
    

    当然,您的其他选择是将内容类型更改为 JSON,但实际上取决于您的要求。

    【讨论】:

    • 我试过这种方式,但它仍然不适合我。请看我的更新。感谢您的帮助。
    • 如果您以mac=string&model=string 格式发送数据,您更新的Device 模型将起作用。但是您的格式是data=string,因此您必须拥有一个名为data 的属性,正如我在回答中所展示的那样。
    • 如果名称有连字符,如何将表单数据映射到我的班级?比如数据={"mac":"0004ED123456","model":"SG6200NX","device-id":"aUniqueId"}
    • @jplara - 我认为您可能需要使用自定义格式化程序 - c-sharpcorner.com/article/…
    • 我找到了另一个选项,自定义格式化程序对我来说太过分了,你可以接受FormDataCollection,这样你就可以访问发布的数据
    【解决方案2】:

    这篇文章很旧,但我在寻找答案时偶然发现了它。我会发布我是如何让我的工作的,也许有人会觉得它有用。

    这是请求:

    POST /api/values HTTP/1.1
    Host: localhost:62798
    Accept: text/json
    Content-Type: application/x-www-form-urlencoded
    Cache-Control: no-cache
    Postman-Token: 51ee1c5f-acbb-335b-35d9-d2b8e62abc74
    
    UID=200&EMAIL=john%40jones.com&FIRST_NAME=John&LAST_NAME=jones&PHONE=433-394-3324&CITY=Seattle&STATE_CODE=WA&ZIP=98105
    

    这是模型:

    public class SampleModel{
        public string UID { get; set; }
    
        public string Email { get; set; }
    
        public string First_Name { get; set; }
    
        public string Last_Name { get; set; }
    
        public string Phone { get; set; }
    
        public string City { get; set; }
    
        public string State_Code { get; set; }
    
        public string Zip { get; set; }
    }
    

    这是自动(FromBody)将 urlencoded 值转换为模型的 POST 方法。

    public HttpResponseMessage Post([FromBody] SampleModel value){
    

    我能够挑选出任何价值,即

        SearchCity(value.City);
        SearchName(value.Last_Name);
    

    【讨论】:

      【解决方案3】:

      您应该创建一个数据对象,例如:

      public class Device
      {
        public string mac {get;set;}
        public string model {get;set;}
      }
      

      然后像这样更改控制器的操作方法,并将对象从消耗传递给此方法

      public void Post(Device deviceData)
      {
          // You can extract data like deviceData.mac, deviceData.model etc
          data.Add(deviceData);
      }
      

      您可以使用流行的库之一json.net 在 C# 中对 json 对象进行序列化/反序列化

      【讨论】:

      • 我试过你的方法,但它似乎不适合我。我仍然得到空值。我的 post 请求标头是 User-Agent: Fiddler Content-type: application/x-www-form-urlencoded Host: localhost:52154,请求正文是 data={"mac":"0004ED123456","model":"SG6200NX "},我只能看到一个空值添加到我的数据字符串列表中。
      【解决方案4】:

      创建模型

      public class MyClass {
          public string mac { get; set; }
          public string model { get; set; }
      }
      

      并使用 .net JavaScriptSerializer().Deserialize

      public void Post([FromBody]string formData){
          MyClass obj = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<MyClass>(formData);
          //get mac and model by obj.mac obj.model
      }
      

      干杯:)

      【讨论】:

      • 完全没有必要自己序列化模型。
      【解决方案5】:

      对于 asp.net core 3.x,您需要提供正确的装饰器来正确处理请求:

      [HttpPost("MyPostHandler")]
      [Consumes("application/x-www-form-urlencoded")]
      public async Task<IActionResult> MyPostHandler([FromForm] string id)
      {
      }
      

      【讨论】:

        【解决方案6】:

        如果您使用的是 Content-type: application/x-www-form-urlencoded 您不能期望收到 JSON。

        我猜您正在使用表单将数据发送到 Web Api 控制器?

        首先您必须将 Content-type 更改为 application/json,然后您必须确保在请求正文中发送 JSON 数据。如果您通过表单发送数据,您可以使用 javascript 从表单数据中创建 JSON 对象。

        要在 C# 中反序列化 JSON,我推荐 Json.NET:http://json.codeplex.com/

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-09-22
          • 2018-08-18
          • 2014-03-30
          • 2020-04-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多