为什么我们必须指定FromBody和FromUri?

时间:2014-07-08 06:45:29

标签: asp.net-web-api

为什么ASP.NET Web API中需要FromBodyFromUri属性?

使用属性和不使用属性有什么区别?

4 个答案:

答案 0 :(得分:152)

当ASP.NET Web API在控制器上调用方法时,它必须为参数设置值,这个过程称为参数绑定

默认情况下,Web API使用以下规则绑定参数:

  • 如果参数是“simple”类型,则Web API会尝试从URI 获取值。简单类型包括.NET基元类型(int,bool,double等),以及TimeSpan,DateTime,Guid,decimal和string,以及具有可以从字符串转换的类型转换器的任何类型。

  • 对于复杂类型,Web API尝试使用媒体类型格式化程序从邮件正文中读取值

因此,如果要覆盖上述默认行为并强制Web API从URI中读取复杂类型,请将[FromUri]属性添加到参数中。要强制Web API从请求正文中读取简单类型,请将[FromBody]属性添加到参数中。

因此,要回答您的问题,Web API中[FromBody][FromUri]属性的需要只是在必要时覆盖默认行为,如上所述。请注意,您可以将两个属性用于控制器方法,但仅针对不同的参数,如演示here所示。

如果你谷歌“web api参数绑定”,网络上有a lot more information

答案 1 :(得分:66)

默认行为是:

  1. 如果参数是 原语 类型(intbooldouble,...) ,Web API尝试从HTTP请求的 URI 中获取值。

  2. 对于 复杂类型 (您自己的对象,例如:Person),Web API会尝试从中读取值HTTP请求的正文

  3. 所以,如果你有:

    • URI中的基本类型
    • 身体中的复杂类型

    ...然后您不必添加任何属性([FromBody][FromUri])。

    但是,如果您在 正文 中有 基本类型 ,那么您必须添加{{ 1}}在WebAPI控制器方法中的基本类型参​​数前面。 (因为默认情况下,WebAPI正在HTTP请求的URI中查找原始类型。)

    或者,如果 URI 中有 复杂类型 ,则必须添加{{1 }}。 (因为默认情况下,WebAPI默认在HTTP请求的主体中查找复杂类型。)

    原始类型:

    [FromBody]

    复杂类型:

    [FromUri]

    只要您在HTTP请求中只发送一个参数 ,这就有效。 发送多个 时,您需要创建一个 自定义模型 ,其中包含以下所有参数:

    public class UsersController : ApiController
    {
        // api/users
        public HttpResponseMessage Post([FromBody]int id)
        {
    
        }
        // api/users/id
        public HttpResponseMessage Post(int id)
        {
    
        }       
    }
    

    来自Microsoft的parameter binding in ASP.NET Web API文档:

      

    当参数具有[FromBody]时,Web API使用Content-Type标头   选择格式化程序。在此示例中,内容类型为   "应用/ JSON"并且请求正文是一个原始的JSON字符串(不是   JSON对象)。 最多允许一个参数从中读取   消息正文。

         

    这应该有效:

    public class UsersController : ApiController
    {       
        // api/users
        public HttpResponseMessage Post(User user)
        {
    
        }
    
        // api/users/user
        public HttpResponseMessage Post([FromUri]User user)
        {
    
        }       
    }
    
         

    这不起作用:

    public class MyModel
    {
        public string MyProperty { get; set; }
        public string MyProperty2 { get; set; }
    }
    
    [Route("search")]
    [HttpPost]
    public async Task<dynamic> Search([FromBody] MyModel model)
    {
        // model.MyProperty;
        // model.MyProperty2;
    }
    
         

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

答案 2 :(得分:11)

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

最多允许一个参数从邮件正文中读取。所以这不起作用:

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

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

请浏览网站了解更多详情:http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

答案 3 :(得分:8)

除了以上答案之外......

[FromUri]也可用于从uri参数绑定复杂类型,而不是从querystring传递参数

对于Ex ..

public class GeoPoint
{
    public double Latitude { get; set; } 
    public double Longitude { get; set; }
}

[RoutePrefix("api/Values")]
public ValuesController : ApiController
{
    [Route("{Latitude}/{Longitude}")]
    public HttpResponseMessage Get([FromUri] GeoPoint location) { ... }
}

可以像:

一样调用
http://localhost/api/values/47.678558/-122.130989