【问题标题】:WebApi - action paramer is null when using [FromBody] attribute and POST methodWeb Api - 使用 [FromBody] 属性和 POST 方法时操作参数为空
【发布时间】:2016-04-14 11:06:04
【问题描述】:

我有这个控制器,我想不通,为什么name参数为空

public class DeviceController : ApiController
{
    [HttpPost]
    public void Select([FromBody]string name)
    {
        //problem: name is always null
    }
}

这是我的路线图:

public void Configuration(IAppBuilder appBuilder)
{
    HttpConfiguration config = new HttpConfiguration();
    config.Routes.MapHttpRoute(
        name: "ActionApi",
        routeTemplate: "api/{controller}/{action}"
    );

    appBuilder.UseWebApi(config);
}

这是我的要求:

POST http://localhost:9000/api/device/Select HTTP/1.2
User-Agent: Fiddler
Host: localhost:9000
Content-Length: 16
Content-Type: application/json

{'name':'hello'}

我还尝试将正文更改为纯字符串:hello

POST http://localhost:9000/api/device/Select HTTP/1.2
User-Agent: Fiddler
Host: localhost:9000
Content-Length: 5
Content-Type: application/json

hello

请求返回 204 是可以的,但参数永远不会映射到发布的值。

*我正在使用自托管的 o​​win 服务。

【问题讨论】:

    标签: c# asp.net-web-api asp.net-mvc-routing owin model-binding


    【解决方案1】:

    在第一个示例中,当 [FromBody] 属性告诉绑定器查找简单类型时,您正在使用复杂对象 {'name':'hello'}

    在第二个示例中,您在正文中提供的值无法解释为简单类型,因为它缺少引号 "hello"

    使用 [FromBody]

    要强制 Web API 从请求正文中读取 简单类型,请将 [FromBody] 属性添加到参数:

    public HttpResponseMessage Post([FromBody] string name) { ... }
    

    在此示例中,Web API 将使用媒体类型格式化程序从请求正文中读取 name 的值。这是一个示例客户端请求。

    POST http://localhost:5076/api/values HTTP/1.1
    User-Agent: Fiddler
    Host: localhost:5076
    Content-Type: application/json
    Content-Length: 7
    
    "Alice"
    

    当参数有 [FromBody] 时,Web API 使用 Content-Type 标头来选择格式化程序。在此示例中,内容类型为“application/json”,请求正文为原始 JSON 字符串(不是 JSON 对象)。

    最多允许从消息体中读取一个参数。所以这行不通:

    // Caution: Will not work!    
    public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }
    

    此规则的原因是请求正文可能存储在只能读取一次的非缓冲流中。

    来源:Parameter Binding in ASP.NET Web API

    【讨论】:

    • 我确实有 FromBody 参数。不同之处在于我使用的是自定义操作
    • 查看示例请求并将其与您的请求进行比较。您会注意到您发布的是 {'name':'hello'} 对象,而不是像 "hello" 这样的简单类型
    • 当我写我的问题时,我试图发布纯字符串,但我错过了引号。我发布了hello,而不是"hello"。我会将其标记为正确的答案,因为它导致了解决方案,但请在您的答案中提及引号,以防其他人像我一样忘记引号
    猜你喜欢
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 2018-06-07
    • 2015-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多