绑定源的设置和顺序不应该取决于HTTP动词吗?

时间:2018-10-16 10:04:45

标签: c# asp.net-core

我有点困惑。我有带有此签名的操作方法(asp.net core 2.1):

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

发出请求时,出现400错误消息:

  

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

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

顺便说一句,一旦我应用[FromQuery]属性,一切都会很好。

第二,为什么首先尝试使用Get方法从主体获取数据?

更新

推断出绑定源后looks like,没有其他任何源被探测。应用[ApiController]属性的原因。没有模型绑定器会尝试从多个来源获取数据。

1 个答案:

答案 0 :(得分:1)

  

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

[ApiController]属性将自定义项添加到ASP.NET Core MVC中使用的Application Model中。这些定制之一是如何确定模型绑定的来源。对于找到的每个动作,将调用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方法从正文中获取数据?

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