【问题标题】:ASP.NET WebAPI Null value in post body?帖子正文中的 ASP.NET WebAPI Null 值?
【发布时间】:2013-12-28 00:36:17
【问题描述】:

我今天刚开始学习WebAPI,我不明白为什么“帐户”总是为空。

请求

Content-Type: application/json; charset=utf-8
Request-Body: {"account":{"email":"awd","password":"awad","isNewsletterSubscribed":false}}

WebAPI

 public class AccountsController : ApiController
    {
        public void Post([FromBody] string account)
            {
                    // account is null
            }
    }

在这种情况下帐户不应该包含json字符串吗?

【问题讨论】:

    标签: asp.net-mvc json asp.net-web-api


    【解决方案1】:

    在这种情况下帐户不应该包含json字符串吗?

    这取决于您在发送请求时设置的特定 Content-Type 请求标头。例如,如果您使用默认的 application/x-www-form-urlencoded,那么您的请求正文负载必须如下所示:

    ={"account":{"email":"awd","password":"awad","isNewsletterSubscribed":false}}
    

    注意开头的= 字符。这是我遇到过的最奇怪的事情之一。如果请求 Web API 不需要参数名称,而只需要值,则您只能从正文中绑定一个参数。

    话虽如此,您的请求负载看起来更像是 JSON。因此,设计一个视图模型并在发送请求时使用Content-Type: application/json 会更有意义。将 JSON 对象绑定到字符串并不常见。

    所以:

    public class UserViewModel
    {
        public string Email { get; set; }
        public string Password { get; set; }
        public bool IsNewsletterSubscribed { get; set; }
    }
    
    public class AccountViewModel
    {
        public UserViewModel Account { get; set; }
    }
    

    然后您的控制器操作将简单地将视图模型作为参数。在这种情况下,您不需要使用 [FromBody] 属性来装饰它,因为按照 Web API 中的约定,默认模型绑定器将尝试绑定来自请求正文的复杂类型:

    public class AccountsController : ApiController
    {
        public HttpResponseMessage Post(AccountViewModel model)
        {
            // work with the model here and return some response
            return Request.CreateResponse(HttpStatusCode.OK);
        }
    }
    

    还请注意,由于 HTTP 是一个请求/响应协议,因此让您的 Web API 控制器操作返回响应消息(如我的示例所示)比仅使用一些 void 方法更有意义。这使代码更具可读性。您立即了解服务器将如何响应以及对指定请求使用什么状态代码。

    【讨论】:

    • 请求头是"application/json; charset=utf-8"
    • 好的,请参阅我的更新答案,了解使用与 JOSN 结构匹配的视图模型来设计它的正确方法。
    • 它有效,谢谢!最后一个问题。为什么我必须用属性 Account 指定一个额外的 AccountViewModel 类?这是否以某种方式融入了名声?
    • 这是因为您的 JSON 对象的形式:它有一个 account 属性,因此您需要将所有内容包装在具有相同名称的属性的外部类中。执行绑定时,模型绑定器将尝试匹配完全相同的结构。如果您的请求正文有效负载如下所示:{"email":"awd","password":"awad","isNewsletterSubscribed":false} 那么您可以直接使用UserViewModel 作为参数。
    猜你喜欢
    • 2015-06-03
    • 1970-01-01
    • 2018-04-18
    • 1970-01-01
    • 2016-04-06
    • 2017-02-02
    • 1970-01-01
    • 2019-04-15
    • 2011-10-10
    相关资源
    最近更新 更多