WebAPI POST [FromBody]没有绑定

mat*_*wen 32 c# asp.net-web-api

我将JSON发布到WebAPI控制器,但模型上的属性没有绑定.

public void Post([FromBody] Models.Users.User model) {
    throw new Exception(model.Id.ToString());
}
Run Code Online (Sandbox Code Playgroud)

原始请求如下:

POST http://diva2.local/siteapi/User HTTP/: diva2.local
Connection: keep-alive
Content-Length:: application/json, text/plain, */*
Origin: http://diva2.local
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.: application/json;charset=UTF: http://diva2.local/Users
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=: ISO-8859-1,utf-8;q=0.7,*;q=: .ASPXAUTH=4; __RequestVerificationToken=Rp_hUysjwCjmsxw2

{"Id":3,"FirstName":"DIVA2","LastName":"User1","Username":"diva1","IsApproved":true,"IsOnlineNow":true,"IsChecked":true}
Run Code Online (Sandbox Code Playgroud)

我能找到的每个例子都告诉我这应该有用,但是model.Id == null.

但是,如果我将JSON更改为:

{User: {"Id":3,"FirstName":"DIVA2","LastName":"User1","Username":"diva1","IsApproved":true,"IsOnlineNow":true,"IsChecked":true}}
Run Code Online (Sandbox Code Playgroud)

一切都正确绑定.

这似乎不正确.我想我可以接受JObject作为参数,并手动绑定它,但感觉就像上面应该Just Work(tm)?

更新:

我已经改变了返回模型的方法,但仍然收到null.

public Models.Users.User Post(Models.Users.User user) {
    return user;
}
Run Code Online (Sandbox Code Playgroud)

并回应:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-MiniProfiler-Ids: ["a0fab514-d725-4d8f-9021-4931dc06ec4a","fdeeb9a8-9e36-41d8-91d3-5348e880e193","c1b4cc86-d7c3-4497-8699-baac9fa79bf1"]
X-Powered-By: ASP.NET
Date: Tue, 21 May 2013 09:06:00 GMT
Content-Length: 4

null
Run Code Online (Sandbox Code Playgroud)

Kir*_*lla 25

您缺少Request中的Content-Type标头.

不幸的是,即使您检查过ModelState,我们也不会抛出任何错误信息.但是,好消息是我们即将发布的版本已修复此行为,您会看到基于状态代码的415响应.

Web API要求Content-Type标头找出正确的格式化程序,以将主体反序列化为操作上的参数.

  • 是`Content-Type:application/json; charset = utf-8`无效? (2认同)

Dar*_*rov 17

以下对我来说非常好:

模型:

public class User
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Username { get; set; }
    public bool IsApproved { get; set; }
    public bool IsOnlineNow { get; set; }
    public bool IsChecked { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

控制器:

public class ValuesController : ApiController
{
    public User Post(User user)
    {
        return user;
    }
}
Run Code Online (Sandbox Code Playgroud)

请求:

POST http://example.com/api/values HTTP/1.1
Connection: keep-alive
Accept: application/json, text/plain, */*
Content-Type: application/json;charset=UTF-8
Host: localhost:8816
Content-Length: 125

{"Id":3,"FirstName":"DIVA2","LastName":"User1","Username":"diva2user1","IsApproved":true,"IsOnlineNow":true,"IsChecked":true}
Run Code Online (Sandbox Code Playgroud)

响应:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
Date: Tue, 21 May 2013 08:59:02 GMT
Content-Length: 125

{"Id":3,"FirstName":"DIVA2","LastName":"User1","Username":"diva2user1","IsApproved":true,"IsOnlineNow":true,"IsChecked":true}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的User,在请求JSON有效负载中没有前缀的情况下,所有内容都很好并且花花公子.

请注意model.Id,因为id如果您在路径定义中将其用作路径的一部分,则可能具有特殊含义.不要混淆两件事(路由参数和来自请求主体有效负载的参数).

  • 这是正确的答案.问题是请求中不应提供{User:}标签,User对象本身应该是root用户. (3认同)
  • 按照我的例子一步一步.使用基本模板创建新的ASP.NET MVC 4应用程序.添加模型(如我的回答所示).添加API控制器(如我的回答所示).使用Fiddler并使用我的答案中显示的有效负载调用此控制器.有用!我做了数百万次,从来没有遇到任何问题. (2认同)

mat*_*wen 11

我的用户模型没有无参数构造函数.


小智 6

我发现我的班级在所有属性上都有内部设置器。

更改 public <property> {get; internal set;}public <property> {get; set;}

修复了我的问题