首页 > 解决方案 > 绑定源的设置和顺序不应该依赖于 HTTP 动词吗?

问题描述

我有点困惑。我有这个签名的动作方法(asp.net core 2.1):

[HttpGet]
public IEnumerable<DeviceTypeDTO> Get(GetDeviceTypeRequest request)

当我提出请求时,我收到 400 错误消息:

需要一个非空的请求正文。

首先,我想了解它为什么停止并且不尝试从查询字符串绑定模型。至少我会在阅读文档后期望这种行为。

顺便说一句,一旦我应用[FromQuery]属性,一切正常。

其次,为什么它首先尝试从 body 获取数据作为Get方法?

更新

看起来在推断绑定源之后没有探测其他源。原因是应用[ApiController]属性。没有它,模型绑定器会尝试从多个来源获取数据。

标签: c#asp.net-core

解决方案


首先,我想了解它为什么停止并且不尝试从查询字符串绑定模型。

[ApiController]属性将自定义添加到ASP.NET Core MVC 中使用的应用程序模型。其中一项定制是如何确定模型绑定的来源。对于找到的每个动作,都会调用其中的InferParameterBindingSources函数ApiBehaviorApplicationModelProvider,其中包括以下代码:

for (var i = 0; i < actionModel.Parameters.Count; i++)
{
    var parameter = actionModel.Parameters[i];
    var bindingSource = parameter.BindingInfo?.BindingSource;
    if (bindingSource == null)
    {
        bindingSource = InferBindingSourceForParameter(parameter);

        parameter.BindingInfo = parameter.BindingInfo ?? new BindingInfo();
        parameter.BindingInfo.BindingSource = bindingSource;
    }
}

这里的调用InferBindingSourceForParameter最相关,其中包括以下代码:

var bindingSource = IsComplexTypeParameter(parameter) ?
    BindingSource.Body :
    BindingSource.Query;

如上所示,代码检查参数(GetDeviceTypeRequest request在您的示例中)以查看它是否复杂(在您的示例中)。鉴于它实际上很复杂,该参数被配置为从请求的正文中使用。

其次,为什么 Get 方法首先尝试从 body 获取数据?

由于这一切都是作为配置 ASP.NET Core MVC 应用程序模型的一部分运行的,因此没有动态上下文来确定这是 GET 还是 POST 请求。话虽如此,我想使用[HttpGet]操作本身的属性来确定请求将是 GET 请求很容易,但我不能确定它是否那么简单。这可能会在 GitHub 上作为 ASP.NET Core MVC 的问题提出,但这将是一个重大更改


推荐阅读