【问题标题】:Why do we have to specify FromBody and FromUri?为什么我们必须指定 FromBody 和 FromUri?
【发布时间】:2014-08-28 19:17:33
【问题描述】:

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

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

【问题讨论】:

  • 只是为了提示何时使用 [FromBody] 注释可能有用:例如,将用户名/密码等静态凭据作为编码在 URL 中的参数发送是不好的做法。尽管 SSL 加密可能会阻止第三方获得对 URL 中参数的读取访问权限,但它仍然是不好的做法,因为这些凭据可能存储在浏览器日志和 equals 中,这绝对是不希望的。在这种情况下,可以使用 [FromBody] 注释来强制将参数存储在 HTTP 消息的正文中,从而引入高

标签: asp.net-web-api


【解决方案1】:

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

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

  • 如果参数是“简单”类型,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 所示。

如果你google“web api参数绑定”,网上有a lotmoreinformation

【讨论】:

  • @user3510527:如果您不想使用这些属性,则不必使用这些属性,只要您遵循默认行为即可。如果要更改默认行为,则需要使用它们。
  • 如果它在做它的默认行为,那么为什么我们需要 ovveride 以及如果我们提到这个属性我们会得到什么好处?
  • @user3510527 您不需要需要覆盖。您可以只使用默认行为。有人可能想要覆盖的一个示例是,如果他们想在请求的正文中提供一个简单的整数,因为默认情况下,它会期望在 URI 中找到它。基本上,您可以根据需要保留默认行为,也可以覆盖,这只是您的一个选项。我不明白这是什么混乱。
  • 我想知道是否可以创建一个名为 JustGetIt 的属性,该属性与添加多个属性(如 [FromBody, FromQuery] 等)的目的相同
【解决方案2】:

默认行为是:

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

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

所以,如果你有:

  • URI 中的原始类型,
  • 体内的复杂类型

...那么您不必添加任何属性([FromBody][FromUri] 都不需要)。

但是,如果你在 body 中有一个原始类型,那么你必须添加@987654328 @ 在您的 WebAPI 控制器方法中的原始类型参数前面。 (因为默认情况下,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;
}

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

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

这应该可行:

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

这不起作用:

// Caution: This won't work!    
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }

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

【讨论】:

  • “最多允许从消息体中读取一个参数”是特别有用的信息
  • 这不是真的。我在 url 中使用了一个 int Id,在 body 中使用了一个对象,它工作得很好。我的对象上确实有 [FromBody],所以这可能是必需的。
【解决方案3】:

除了以上答案..

[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

【讨论】:

    【解决方案4】:

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

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

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

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

    请浏览网站了解更多详情: https://docs.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-17
      • 2014-03-10
      • 2020-07-17
      相关资源
      最近更新 更多