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

Javascript 如何将json POST数据作为对象传递给Web API方法?,javascript,asp.net-mvc,json,asp.net-mvc-4,asp.net-web-api,Javascript,Asp.net Mvc,Json,Asp.net Mvc 4,Asp.net Web Api,ASP.NET MVC4 Web API应用程序定义了保存客户的post方法。 客户以json格式在POST请求正文中传递。 post方法中的Customer参数包含属性的空值 如何解决此问题,以便将发布的数据作为客户对象传递 如果可能,应该使用内容类型:application/x-www-form-urlencoded,因为我不知道如何在发布表单的javascript方法中更改它 控制器: public class CustomersController : ApiController {

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

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

如果可能,应该使用内容类型:application/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; }
     }
[HttpPost]
[AcceptVerbs("POST")]
public string POSTMe([FromBody]Models.UserActivity _activity)
{
    return "hello";
}
请求:

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

编辑:2017年10月31日

同样的代码/方法也适用于Asp.Net Core 2.0。主要的区别是,在asp.net内核中,web api控制器和Mvc控制器都合并到一个控制器模型中。因此,您的返回类型可能是
IActionResult
或其实现之一(例如:
OkObjectResult


使用

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

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

下面的代码可以正常工作(已测试)

结果

contentType
属性告诉服务器我们正在以JSON格式发送数据。因为我们发送了一个JSON数据结构,所以模型绑定将正常进行

如果检查ajax请求的头,可以看到
Content-Type
值设置为
application/json

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


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

发布复杂对象 假设您有一个复杂的视图模型类作为WebAPI操作方法参数,如下所示

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;}
}
在撰写本文时,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 :)
});
模型绑定适用于某些属性,但不是所有属性!为什么? 如果不使用
[FromBody]
属性装饰web api方法参数

[HttpPost]
public CreateUserViewModel Save(CreateUserViewModel m)
{
    return m;
}
并发送模型(原始javascript对象,不是JSON格式),而不指定contentType属性值

$.ajax({
    type: "POST",
    data: model,
    url: "../product/save"
}).done(function (res) {
     console.log('res', res);
});
模型绑定将适用于模型上的平面属性,而不是类型为复杂/其他类型的属性。在我们的例子中,
Id
Name
属性将正确绑定到参数
m
,但是
标记
属性将是一个空列表

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

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

在webapi中使用POST可能很棘手! 希望在已经正确的答案上添加

将特别关注POST,因为处理GET是微不足道的。我不认为有多少人会四处搜索来解决GET with WebAPI的问题。无论如何

如果您的问题是-在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中

第三,首先,在一个动作中发布多个简单类型是不可能的。 此外,还有一种特殊格式,甚至可以发布单个简单类型(除了在查询字符串或REST样式中传递参数之外)。 正是在这一点上,我与Rest客户端(如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"}
注意到奇怪的语法了吗

不管怎样,让我们忘掉那个故事吧。继续:

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

假设action方法接受一个具有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;
}

所有这些,都为我工作!!干杯

我刚刚玩过这个,发现了一个相当奇怪的结果。假设您在C#中的类中有公共属性,如下所示:

public class Customer
{
    public string contact_name;
    public string company_name;
}
var customer = {contact_name :"Scott",company_name:"HP"};
$.ajax({
    type: "POST",
    data :JSON.stringify(customer),
    url: "api/Customer",
    contentType: "application/json"
});
public class Customer
{
    public string contact_name { get; set; }
    public string company_name { get; set; }
}
然后,您必须按照Shyju的建议执行JSON.stringify技巧,并将其命名为:

public class Customer
{
    public string contact_name;
    public string company_name;
}
var customer = {contact_name :"Scott",company_name:"HP"};
$.ajax({
    type: "POST",
    data :JSON.stringify(customer),
    url: "api/Customer",
    contentType: "application/json"
});
public class Customer
{
    public string contact_name { get; set; }
    public string company_name { get; set; }
}
但是,如果在类上定义getter和setter,如下所示:

public class Customer
{
    public string contact_name;
    public string company_name;
}
var customer = {contact_name :"Scott",company_name:"HP"};
$.ajax({
    type: "POST",
    data :JSON.stringify(customer),
    url: "api/Customer",
    contentType: "application/json"
});
public class Customer
{
    public string contact_name { get; set; }
    public string company_name { get; set; }
}
然后你可以更简单地称之为:

$.ajax({
    type: "POST",
    data :customer,
    url: "api/Customer"
});
这将使用HTTP标头:

Content-Type:application/x-www-form-urlencoded
我不太确定这里发生了什么,但它看起来像框架中的一个bug(功能?)。可能不同的绑定方法正在调用不同的“适配器”,而application/json-one的适配器使用公共属性,而表单编码数据的适配器则不使用

但我不知道哪一种是最佳实践。

使用JSON.stringify()获取JSON格式的字符串,确保在进行AJAX调用时传递以下属性:

  • contentType:'应用程序/json'
下面给出了对asp.net web api进行ajax后期调用的jquery代码:

var乘积=
JSON.stringify({
productGroup:“Fablet”,
if (ModelState.IsValid)
Content = new StringContent(update.Status)
var IndexInfo = JSON.stringify(this.scope.IndexTree);
this.$http.post('../../../api/EvaluationProcess/InsertEvaluationProcessInputType', "'" + IndexInfo + "'" ).then((response: any) => {}
public ApiResponce InsertEvaluationProcessInputType([FromBody]string IndexInfo)
    {
var des = (ApiReceivedListOfObjects<TempDistributedIndex>)Newtonsoft.Json.JsonConvert.DeserializeObject(DecryptedProcessInfo, typeof(ApiReceivedListOfObjects<TempDistributedIndex>));}
public class ApiReceivedListOfObjects<T>
    {
        public List<T> element { get; set; }

    }
var resp = @"
    {
        ""element"": [
        {
            ""A"": ""A Jones"",
            ""B"": ""500015763""
        },
        {
            ""A"": ""B Smith"",
            ""B"": ""504986213""
        },
        {
            ""A"": ""C Brown"",
            ""B"": ""509034361""
        }
        ]
    }";