为什么在ASP.NET Web API中需要使用FromBody
和FromUri
属性?
使用这些属性和不使用它们有什么区别?
为什么在ASP.NET Web API中需要使用FromBody
和FromUri
属性?
使用这些属性和不使用它们有什么区别?
[FromBody]
和 [FromUri]
属性只是为了覆盖默认行为(如上所述),如果必要的话。请注意,你可以在控制器方法中同时使用这两个属性,但只能用于不同的参数,如 here 所示。JustGetIt
的属性,它的作用与添加多个属性如[FromBody, FromQuery]
等相同。 - The Muffin Man如果参数是一个基本类型(例如:int
,bool
,double
等),Web API会尝试从HTTP请求的URI获取该值。
对于复杂类型(例如:您自己的对象,例如:Person
),Web API会尝试从HTTP请求的主体中读取该值。
因此,如果您有:
...那么您不需要添加任何属性(既不是[FromBody]
也不是[FromUri]
)。
但是,如果您在主体中有一个基本类型,则必须在WebAPI控制器方法中的基本类型参数前面添加[FromBody]
。(因为默认情况下,WebAPI正在查找HTTP请求的URI中的基本类型。)
或者,如果您在URI中有一个复杂类型,则必须添加[FromUri]
。(因为默认情况下,WebAPI正在HTTP请求的主体中查找复杂类型。)
基本类型:
public class UsersController : ApiController
{
// api/users
public HttpResponseMessage Post([FromBody]int id)
{
}
// api/users/id
public HttpResponseMessage Post(int id)
{
}
}
复杂类型:
public class UsersController : ApiController
{
// api/users
public HttpResponseMessage Post(User user)
{
}
// api/users/user
public HttpResponseMessage Post([FromUri]User user)
{
}
}
只要您在HTTP请求中发送一个参数,这就可以正常工作。但是,当发送多个参数时,您需要创建一个自定义模型,该模型包含您所有的参数,如下所示:
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;
}
以下是微软关于ASP.NET Web API参数绑定的文档:
When a parameter has [FromBody], Web API uses the Content-Type header to select a formatter. In this example, the content type is "application/json" and the request body is a raw JSON string (not a JSON object). At most one parameter is allowed to read from the message body.
This should work:
public HttpResponseMessage Post([FromBody] string name) { ... }
This will not work:
// Caution: This won't work! public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }
The reason for this rule is that the request body might be stored in a non-buffered stream that can only be read once.
仅为以上答案添加信息...
[FromUri]也可以用来从URI参数绑定复杂类型,而不是通过查询字符串传递参数。
例如...
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
// Caution: Will not work!
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }
这个规则的原因是请求正文可能存储在非缓冲流中,该流只能被读取一次。
请访问以下网站了解更多详情: https://learn.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api