原因
经常有朋友遇到webapi参数传递问题,自己也碰到过一些坑,在此记录下正确的姿势,简单参数传递相信没有人会有问题,容易出现问题的是对象参数和表单参数。
1、WebApi5.2.3有FromBody和无FromBody
控制器代码如下:
public class ValuesController : ApiController { // POST api/values [HttpPost] [Route("~/api/Values/Post")] public UserModel Post(UserModel value) { return value; } [HttpPost] [Route("~/api/Values/Put")] // PUT api/values/5 public UserModel Put([FromBody]UserModel value) { return value; } } public class UserModel { public string UserName { get; set; } public string Password { get; set; } }
对应的JS请求代码如下,对于有FromBody的Put请求来说,两种请求方式都是可以的:
<script type="text/javascript"> $(function () { $('#btnPost').click(function () { $.ajax({ url: '/api/Values/Post', data: { UserName: 'Admin', Password: '123456' }, method: 'POST', dataType: 'json' }).done(function (result) { $('#txtPost').val(JSON.stringify(result)); }) }) $('#btnPostFromBody').click(function () { $.ajax({ url: '/api/Values/Put', data: { UserName: 'Admin', Password: '123456' }, method: 'POST', dataType: 'json' }).done(function (result) { $('#txtPostFromBody').val(JSON.stringify(result)); }) $.ajax({ url: '/api/Values/Put', data: JSON.stringify({ UserName: 'Admin', Password: '123456' }), method: 'POST', dataType: 'json', contentType: 'application/json' }).done(function (result) { $('#txtPostFromBody').val(JSON.stringify(result)); }) }) })
有图有真相

2、Asp .Net Core 有FromBody和无FromBody
服务端代码如下:
public class ValuesController : Controller { // POST api/values [HttpPost] [Route("~/api/Values/Post")] public UserModel Post(UserModel value) { return value; } [HttpPost] [Route("~/api/Values/Put")] // PUT api/values/5 public UserModel Put([FromBody]UserModel value) { return value; } } public class UserModel { public string UserName { get; set; } public string Password { get; set; } }
js请求代码有所不同,FromBody不再提供兼容支持 只能采用application/json方式提交:
$('#btnPost').click(function () {
$.ajax({
url: '/api/Values/Post',
data: {
UserName: 'Admin',
Password: '123456'
},
method: 'POST',
dataType: 'json'
}).done(function (result) {
$('#txtPost').val(JSON.stringify(result));
})
})
$('#btnPostFromBody').click(function () {
$.ajax({
url: '/api/Values/Put',
data: JSON.stringify({
UserName: 'Admin',
Password: '123456'
}),
method: 'POST',
dataType: 'json',
contentType: 'application/json'
}).done(function (result) {
$('#txtPostFromBody').val(JSON.stringify(result));
})
})
调用结果:

3、Asp .Net Core 之From表单
有时候难免有上传文件的需求,对象存储这个嘛有的时候客户不愿意多花钱或者把文件存到别人的服务器上,只能自己存了。为了少点垃圾文件还是和表单一起提交吧。
控制器代码:

js请求代码,注意红字:
$('#btnFromForm').click(function () {
var data = new FormData();
data.append('UserName', 'Admin');
data.append('Password', '123456');
data.append('Photo', document.getElementById('txtPhoto').files[0]);
$.ajax({
url: '/api/Values/RegisterUser',
data: data,
method: 'POST',
dataType: 'json',
contentType: false,
processData: false
}).done(function (result) {
$('#txtFromForm').val(JSON.stringify(result));
})
})
请求结果:

最后说一句:接口的参数如果是对象,参数名一定不能与改对象的属性名相同(不区分大小写),否则属性的值会全部为null,我猜是微软认为有循环依赖了。比如以上例子中,UserModel中含有UserName,Password,Photo属性,则接口中UserModel参数的名字一定不能是UserName,Password,Photo(不区分大小写),曾经被这个问题坑了2天。