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

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

如何解决这个问题,以便张贴的数据将作为客户对象传递?

如果可能的话,Content-Type: 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; }
}

要求:

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"}
862530 次浏览

__abc0: 31/10/2017

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


使用

contentType:"application/json"

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

模型绑定器会将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-Type值被设置为application/json

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


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

发布一个复杂对象

假设你有一个复杂的视图模型类作为你的web api action方法参数

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 MVC6是最新的稳定版本,在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);
});

模型绑定将适用于模型上的平面属性,而不适用于复杂类型/其他类型的属性。在本例中,IdName属性将被正确地绑定到参数m,但Tags属性将是一个空列表。

如果你使用的是短版本$.post,在发送请求时将使用默认的Content-Type,也会出现同样的问题。

$.post("../product/save", model, function (res) {
//res contains the markup returned by the partial view
console.log('res', res);
});
在webapi中使用POST是很棘手的! 想要添加到已经正确的答案..

将特别关注POST,因为处理GET是微不足道的。我不认为有很多人会到处寻找通过webapi解决GET问题的方法。不管怎样. .

如果你的问题是-在MVC Web Api中,如何-使用自定义动作方法名而不是通用的HTTP动词?-执行多个帖子?-发布多个简单类型?- Post复杂类型通过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]属性装饰。使用[ActionName("MyAction")]来分配自定义名称,等等。将在下面第四点讲到jQuery

第三,首先,在一个动作中发布多个简单的类型是不可能的。 此外,还有一个特殊格式来发布一个单一简单型(除了在查询字符串或REST样式中传递参数)。 这一点让我埋头Rest客户端(如Fiddler和Chrome的高级Rest客户端扩展),在网上搜索了近5个小时,最终,下面的URL被证明是有帮助的。会引用相关内容的链接可能会转死!< / p >
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()将立即进入角色:

假设操作方法接受一个Person对象,该对象具有id和名称。因此,从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;
}

那么你必须处理JSON。按照Shyju的建议,stringify trick,并如下所示:

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

然而,如果你在你的类上定义getter和setter,就像这样:

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的适配器可以使用公共属性,而表单编码数据的适配器则不行。

不过,我不知道哪种做法才是最佳做法。

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

  • contentType:“application / json”

下面是jquery代码让ajax post调用asp.net web api:

var product =
JSON.stringify({
productGroup: "Fablet",
productId: 1,
productName: "Lumia 1525 64 GB",
sellingPrice: 700
});


$.ajax({
URL: 'http://localhost/api/Products',
type: 'POST',
contentType: 'application/json',
data: product,
success: function (data, status, xhr) {
alert('Success!');
},
error: function (xhr, status, error) {
alert('Update Error occurred - ' + error);
}
});

确保您的WebAPI服务期望一个强类型对象,其结构与您传递的JSON相匹配。确保你对要发布的JSON进行了stringify。

这是我的JavaScript(使用AngluarJS):

$scope.updateUserActivity = function (_objuserActivity) {
$http
({
method: 'post',
url: 'your url here',
headers: { 'Content-Type': 'application/json'},
data: JSON.stringify(_objuserActivity)
})
.then(function (response)
{
alert("success");
})
.catch(function (response)
{
alert("failure");
})
.finally(function ()
{
});

这是我的WebAPI控制器:

[HttpPost]
[AcceptVerbs("POST")]
public string POSTMe([FromBody]Models.UserActivity _activity)
{
return "hello";
}

下面的代码返回json格式的数据,而不是xml - web API 2

在全局中放入以下一行。asax文件

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
@model MVCClient.Models.ProductDetails


@{
ViewBag.Title = "ProductDetails";
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script type="text/javascript">


$(document).ready(function () {
$("#Save").click(function () {
var ProductDetails = new Object();
ProductDetails.ProductName =  $("#txt_productName").val();
ProductDetails.ProductDetail = $("#txt_desc").val();
ProductDetails.Price= $("#txt_price").val();
$.ajax({
url: "http://localhost:24481/api/Product/addProduct",
type: "Post",
dataType:'JSON',
data:ProductDetails,


success: function (data) {
alert('Updated Successfully');
//window.location.href = "../Index";
},
error: function (msg) { alert(msg); }
});
});
});
</script>
<h2>ProductDetails</h2>


<form id="form1" method="post">
<fieldset>
<legend>ProductDetails</legend>




<div class="editor-label">
@Html.LabelFor(model => model.ProductName)
</div>
<div class="editor-field">


<input id="txt_productName" type="text" name="fname">
@Html.ValidationMessageFor(model => model.ProductName)
</div>


<div class="editor-label">
@Html.LabelFor(model => model.ProductDetail)
</div>
<div class="editor-field">


<input id="txt_desc" type="text" name="fname">
@Html.ValidationMessageFor(model => model.ProductDetail)
</div>


<div class="editor-label">
@Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">


<input id="txt_price" type="text" name="fname">
@Html.ValidationMessageFor(model => model.Price)
</div>






<p>
<input id="Save" type="button" value="Create" />
</p>
</fieldset>


</form>
<div>
@Html.ActionLink("Back to List", "Index")
</div>


</form>






@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}

微软给出了一个很好的例子:

https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-1

首先验证请求

if (ModelState.IsValid)

然后使用序列化的数据。

Content = new StringContent(update.Status)

这里的“Status”是复杂类型中的一个字段。序列化是由。net完成的,不用担心。

1)在你的客户端,你可以给你发送http。在下面这样的字符串中提交请求

var IndexInfo = JSON.stringify(this.scope.IndexTree);
this.$http.post('../../../api/EvaluationProcess/InsertEvaluationProcessInputType', "'" + IndexInfo + "'" ).then((response: any) => {}

2)然后在你的web api控制器中你可以反序列化它

public ApiResponce InsertEvaluationProcessInputType([FromBody]string IndexInfo)
{
var des = (ApiReceivedListOfObjects<TempDistributedIndex>)Newtonsoft.Json.JsonConvert.DeserializeObject(DecryptedProcessInfo, typeof(ApiReceivedListOfObjects<TempDistributedIndex>));}

3)你的ApiReceivedListOfObjects类应该如下所示

public class ApiReceivedListOfObjects<T>
{
public List<T> element { get; set; }


}

4)确保你的序列化字符串(这里的IndexInfo)变得像下面的结构在JsonConvert。步骤2中的反序列化对象命令

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