Web Api 中的语法糖 - 如何省略 [FromBody]

Syntactic sugar in Web Api - how to omit [FromBody]

是否可以省略写[FromBody]

[HttpPost]
public string SomeMethod([FromBody]SomeModel model)
{
    return "OK";
}

我应该应用一些全局属性吗?如何实现?

实现此目的的方法可能不止一种..这是一种方法:自定义 ActionValueBinder..

  1. 编写自定义 class 以扩展 DefaultActionValueBinder

    public class 来自BodyParameterBindingActionValueBinder : DefaultActionValueBinder

  2. 重写 GetParameterBinding 方法。

    protected override HttpParameterBinding 
              GetParameterBinding(HttpParameterDescriptor parameter)
    {
        return parameter.ActionDescriptor.SupportedHttpMethods.Contains(HttpMethod.Post)
        ||  parameter.ActionDescriptor.SupportedHttpMethods.Contains(HttpMethod.Put) ?
               parameter.BindWithAttribute(new FromBodyAttribute()) : 
               base.GetParameterBinding(parameter);
    }
    

基本上我们要说的是,如果 Web API 系统收到 POST 或 PUT 调用,请将 FromBody 作为默认参数绑定方法。

  1. 一旦我们有了自定义活页夹,就在全球注册它。

    GlobalConfiguration.Services.Replace(typeof(IActionValueBinder), new FromBodyParameterBindingActionValueBinder());

这样做的目的是,对于每个 POST/PUT 请求,Web API 将尝试根据请求 Body 创建模型。您不需要显式提供 [FromBody] 属性。


话虽如此,您需要了解您所请求内容的含义..

Web API 有一些关于模型绑定的默认规则。 (可以更改)

  1. 首先是原始操作参数,查看查询字符串
  2. 然后请求 body.
  3. 首先是复杂的操作参数,查看请求 body。
  4. 然后查询字符串。

此外,web api 只能读取第一个 [FromBody] 操作参数。无法从 body.

读取后续参数

我列举上述规则的原因是,当您希望创建某些模型时,您会意识到这种行为,但网络 api 似乎并没有从 body.

对我来说,明确提供 [FromBody] 更具可读性和可预测性..但是如果你在 Http 动词方面完全控制你的 APIs 并期望所有请求通过 Body,这是一件非常有效的事情。

MVC 5 中的模型绑定属性为操作上的每个参数指定一个“BindingSource”,也可以为控制器上的每个 属性 指定。您可以具体查看 BodyModelBinder

中的 FromBody 属性的代码

首先让我说,你应该注意从 beta6 开始(我认为 beta5 中的某些点),不允许 parameters/properties 和 BindingSource.Body,如果您将多个参数保留为默认值,您将无法使用您的操作。如果您想注释更多,这实际上可能是可取的;我猜你不会。

您可以在DefaultApiDescriptionProvider中看到设置了默认来源;不幸的是,此时没有钩子可以绑定,方法本身是私有的而不是虚拟的;你需要重新实现整个 class.

不过,一旦你拥有它,就可以很容易地在你的 ConfigureServices 中注册它来代替使用它:

services.TryAdd(ServiceDescriptor.Transient<IApiDescriptionProvider, YourApiDescriptionProvider>());

你也可以看到the default being registered in the source