ASP.NET MVC4 Web API应用程序定义了post方法来保存客户。 客户在POST请求体中以json格式传递。 在post方法中的客户参数包含空的属性值。
如何解决这个问题,使发布的数据以客户对象的形式传递?
如果可能的话,应该使用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"}
EDIT :31/10/2017
同样的代码/方法也适用于Asp.Net Core 2.0。主要的区别是,在asp.net core中,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"
});
});
结果
。
contentType
属性告诉服务器,我们正在发送JSON格式的数据。由于我们发送的是JSON数据结构,模型绑定将正常发生。
如果你检查ajax请求的头文件,你可以看到Content-Type
值被设置为application/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 :)
});
如果你没有用[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',但
Tags'属性将是一个空列表。
如果你使用简短的版本,$.post
,在发送请求时将使用默认的内容类型,也会发生同样的问题。
$.post("../product/save", model, function (res) {
//res contains the markup returned by the partial view
console.log('res', res);
});
在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]属性进行装饰。使用[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":"[email protected]"}
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;
}
那么你必须按照Shyju建议的JSON.stringify技巧,像这样调用它。
var customer = {contact_name :"Scott",company_name:"HP"};
$.ajax({
type: "POST",
data :JSON.stringify(customer),
url: "api/Customer",
contentType: "application/json"
});
然而,如果你像这样在你的类上定义getters和setters。
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
我不太清楚这里发生了什么,但它看起来像是框架中的一个错误(功能?据推测,不同的绑定方法是在调用不同的适配器,虽然application/json的适配器可以使用公共属性,但用于表单编码数据的适配器却不能。
我不知道哪种方法被认为是最佳做法。