如何将 json POST 数据作为对象传递给 Web API 方法?

ASP.NET MVC4 Web API 应用程序定义了保存客户的发布方法。客户在 POST 请求正文中以 json 格式传递。post 方法中的客户参数包含属性的 null 值。

如何解决此问题,以便发布的数据将作为客户对象传递?

如果可能的话,内容类型:应用程序/ x-www-form-urlencoded应该使用,因为我不知道如何在javascript方法中更改它。

控制器:

public class CustomersController : ApiController {

  public object Post([FromBody] Customer customer)
        {
            return Request.CreateResponse(HttpStatusCode.OK,
            new
            {
                customer = customer
            });
        }
    }
}

public class Customer
    {
        public string company_name { get; set; }
        public string contact_name { get; set; }
     }

请求:

POST http://localhost:52216/api/customers HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

{"contact_name":"sdfsd","company_name":"ssssd"}

答案 1

编辑 : 31/10/2017

相同的代码/方法也适用于 Asp.Net Core 2.0。主要区别在于,在 asp.net 内核中,Web API 控制器和 Mvc 控制器都合并为单个控制器模型。因此,您的返回类型可能是或它的实现之一(例如:IActionResultOkObjectResult)


contentType:"application/json"

您需要在发送时使用方法将其转换为JSON字符串,JSON.stringify

模型绑定器会将 json 数据绑定到类对象。

下面的代码将正常工作(经过测试)

$(function () {
    var customer = {contact_name :"Scott",company_name:"HP"};
    $.ajax({
        type: "POST",
        data :JSON.stringify(customer),
        url: "api/Customer",
        contentType: "application/json"
    });
});

结果

enter image description here

contentType属性告诉服务器我们正在以 JSON 格式发送数据。由于我们发送了JSON数据结构,因此模型绑定将正确进行。

如果检查 ajax 请求的标头,可以看到该值设置为 。Content-Typeapplication/json

如果未显式指定 contentType,它将使用默认内容类型,即application/x-www-form-urlencoded;


在 2015 年 11 月进行编辑,以解决评论中提出的其他可能问题

发布复杂对象

假设您有一个复杂的视图模型类作为 Web API 操作方法参数,如下所示

public class CreateUserViewModel
{
   public int Id {set;get;}
   public string Name {set;get;}  
   public List<TagViewModel> Tags {set;get;}
}
public class TagViewModel
{
  public int Id {set;get;}
  public string Code {set;get;}
}

你的 Web API 端点就像

public class ProductController : Controller
{
    [HttpPost]
    public CreateUserViewModel Save([FromBody] CreateUserViewModel m)
    {
        // I am just returning the posted model as it is. 
        // You may do other stuff and return different response.
        // Ex : missileService.LaunchMissile(m);
        return m;
    }
}

在撰写本文时,ASP.NET MVC 6 是最新的稳定版本,在 MVC6 中,Web API 控制器和 MVC 控制器都继承自 Microsoft.AspNet.Mvc.Controller 基类。

要将数据从客户端发送到该方法,下面的代码应该可以正常工作

//Build an object which matches the structure of our view model class
var model = {
    Name: "Shyju",
    Id: 123,
    Tags: [{ Id: 12, Code: "C" }, { Id: 33, Code: "Swift" }]
};

$.ajax({
    type: "POST",
    data: JSON.stringify(model),
    url: "../product/save",
    contentType: "application/json"
}).done(function(res) {       
    console.log('res', res);
    // Do something with the result :)
});

模型绑定适用于某些属性,但不是全部!为什么?

如果不使用属性修饰 Web API 方法参数[FromBody]

[HttpPost]
public CreateUserViewModel Save(CreateUserViewModel m)
{
    return m;
}

并在不指定 contentType 属性值的情况下发送模型(原始 javascript 对象,而不是 JSON 格式)

$.ajax({
    type: "POST",
    data: model,
    url: "../product/save"
}).done(function (res) {
     console.log('res', res);
});

模型绑定将适用于模型上的平面属性,而不是类型为复杂/另一种类型的属性。在我们的例子中,属性将正确绑定到参数,但属性将是一个空列表。IdNamemTags

如果您使用的是简短版本,则会出现同样的问题,该版本在发送请求时将使用默认的内容类型。$.post

$.post("../product/save", model, function (res) {
    //res contains the markup returned by the partial view
    console.log('res', res);
});

答案 2

在 webapi 中使用 POST 可能很棘手!想添加到已经正确的答案..

将特别关注POST,因为处理GET是微不足道的。我不认为很多人会四处寻找解决带有webapis的GET问题。无论如何。。

如果您的问题是 - 在MVC Web Api中,如何 - 使用通用HTTP动词以外的自定义操作方法名称?- 执行多个帖子?- 发布多个简单类型?- 通过jQuery发布复杂类型?

那么以下解决方案可能会有所帮助:

首先,要在 Web API 中使用自定义操作方法,请将 Web API 路由添加为:

public static void Register(HttpConfiguration config)
{
    config.Routes.MapHttpRoute(
        name: "ActionApi",
        routeTemplate: "api/{controller}/{action}");
}

然后,您可以创建如下操作方法:

[HttpPost]
public string TestMethod([FromBody]string value)
{
    return "Hello from http post web api controller: " + value;
}

现在,从浏览器控制台触发以下jQuery

$.ajax({
    type: 'POST',
    url: 'http://localhost:33649/api/TestApi/TestMethod',
    data: {'':'hello'},
    contentType: 'application/x-www-form-urlencoded',
    dataType: 'json',
    success: function(data){ console.log(data) }
});

其次,要执行多个帖子,很简单,创建多个操作方法并用[HttpPost]attrib装饰。使用 [ActionName(“MyAction”)] 分配自定义名称等。将在下面的第四点来到jQuery

第三,首先,在单个操作中发布多个SIMPLE类型是不可能的。此外,有一种特殊的格式可以发布单个简单类型(除了在查询字符串或REST样式中传递参数)。正是这一点让我与Rest Clients(如Fiddler和Chrome的高级REST客户端扩展)一起敲头,并在网络上搜索了近5个小时,最终,以下URL被证明是有帮助的。会引用相关内容的链接可能会死!

Content-Type: application/x-www-form-urlencoded
in the request header and add a = before the JSON statement:
={"Name":"Turbo Tina","Email":"na@Turbo.Tina"}

PS:注意到了奇特的语法吗?

http://forums.asp.net/t/1883467.aspx?The+received+value+is+null+when+I+try+to+Post+to+my+Web+Api

无论如何,让我们克服这个故事。继续前进:

第四,通过jQuery发布复杂类型,当然,$.ajax()将立即进入角色:

假设操作方法接受具有 id 和名称的 Person 对象。所以,从javascript:

var person = { PersonId:1, Name:"James" }
$.ajax({
    type: 'POST',
    url: 'http://mydomain/api/TestApi/TestMethod',
    data: JSON.stringify(person),
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    success: function(data){ console.log(data) }
});

该操作将如下所示:

[HttpPost]
public string TestMethod(Person person)
{
    return "Hello from http post web api controller: " + person.Name;
}

以上所有,都为我工作!干杯!