当前位置:网站首页>1 句代码,搞定 ASP.NET Core 绑定多个源到同一个类
1 句代码,搞定 ASP.NET Core 绑定多个源到同一个类
2022-07-29 04:44:00 【dotNET跨平台】
问题
有群友希望将路由中的信息绑定到一个Dto对象中:
public class DDDDDto
{
[FromRoute(Name ="collectionId")]
public Guid collectionId { get; set; }
[BindProperty(Name = "relativeUrl")]
public string relativeUrl { get; set; }
}这样就不用在 Action 中定义一堆参数了:
[HttpGet("collections/{collectionId}/patn/{relativeUrl}/children", Name = "QueryChildrenOfItem")]
public async Task<DDDDDto> QueryChildren(
[FromRoute(Name = "collectionId")] Guid collectionId,
[FromRoute(Name = "relativeUrl")] string relativeUrl)想法很好,对吧!
但是实际运行,却发现达不到想要的效果,没有绑定到数据:

这说明 ASP.NET Core 默认是无法将其他不同的源绑定到单个类的。
那能不能换种方式,解决这个问题呢?
源码探究
首先,我们查看源码,想看看FromRouteAttribute是如何工作的。
仅在InferParameterBindingInfoConvention类中找到一处调用:
var message = Resources.FormatApiController_MultipleBodyParametersFound(
action.DisplayName,
nameof(FromQueryAttribute),
nameof(FromRouteAttribute),
nameof(FromBodyAttribute));
message += Environment.NewLine + parameters;
throw new InvalidOperationException(message);结果,这段代码还是用来生成异常信息的!?
不过,这段代码前面的部分引起了我们的注意:

这明显是在设置绑定源信息:
bindingSource = InferBindingSourceForParameter(parameter);
parameter.BindingInfo = parameter.BindingInfo ?? new BindingInfo();
parameter.BindingInfo.BindingSource = bindingSource;InferBindingSourceForParameter的实现代码如下:
internal BindingSource InferBindingSourceForParameter(ParameterModel parameter)
{
if (IsComplexTypeParameter(parameter))
{
if (_serviceProviderIsService?.IsService(parameter.ParameterType) is true)
{
return BindingSource.Services;
}
return BindingSource.Body;
}
if (ParameterExistsInAnyRoute(parameter.Action, parameter.ParameterName))
{
return BindingSource.Path;
}
return BindingSource.Query;
}单个类肯定是IsComplexTypeParameter, 这将让方法返回BindingSource.Body。
这也正好解释了: 正常情况下,如果使用单个类作为 Action 参数,默认从 Body 源绑定的原因。
那么,能否改变 ASP.NET Core 这一默认的绑定行为吗?
柳暗花明
继续查看InferParameterBindingInfoConvention的使用,我们发现它的调用,居然在一个条件分支内:
if (!options.SuppressInferBindingSourcesForParameters)
{
var serviceProviderIsService = serviceProvider.GetService<IServiceProviderIsService>();
var convention = options.DisableImplicitFromServicesParameters || serviceProviderIsService is null ?
new InferParameterBindingInfoConvention(modelMetadataProvider) :
new InferParameterBindingInfoConvention(modelMetadataProvider, serviceProviderIsService);
ActionModelConventions.Add(convention);
}那么,如果让SuppressInferBindingSourcesForParameters设为true,会有什么效果呢?
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressInferBindingSourcesForParameters = true;
});下面,就是见证奇迹的时刻:

我们也尝试了从其他源,比如 Query,传递数据,都可以正常绑定。
1 句代码,我们搞定了 ASP.NET Core 将多个来源绑定到同一个类的功能。
结论
后来,我们在官方文档(https://docs.microsoft.com/zh-cn/aspnet/core/web-api/?view=aspnetcore-6.0)找到了解释:

当没有在参数上显式指定[FromXXX]时,ASP.NET Core 会进行绑定源推理,比如会推断单个类的绑定源为 Body。
设置 SuppressInferBindingSourcesForParameter 为 true,则会禁用绑定源推理。ASP.NET Core 运行时会尝试按顺序从所有源中拉取数据进行绑定。
添加微信号【MyIO666】,邀你加入技术交流群
边栏推荐
- post导出数据,返回
- leetcode 763. Partition Labels 划分字母区间(中等)
- un7.28:redis客户端常用命令。
- IOS interview preparation - IOS
- img 响应式图片的实现(含srcset属性、sizes属性的使用方法,设备像素比详解)
- [c language] use the reverse order output of the linked list (bidirectional linked list)
- Opencv environment construction
- The most complete NLP Chinese and English stop words list in the whole station (including punctuation marks, which can be copied directly)
- After the spinning up installation is completed, use the tutorial to test whether it is successful. There are library "Glu" not found and 'from pyglet.gl import * error solutions
- Simply change the picture color
猜你喜欢

MySQL - deep parsing of MySQL index data structure

Use of construction methods

MySQL - 聚簇索引和辅助索引

STL source code analysis (Hou Jie) notes -- Classification and testing of stl containers

Take you to understand JS array

GCC基础知识

(heap sort) heap sort is super detailed, I don't believe you can't (C language code implementation)

用 ZEGO Avatar 做一个虚拟人|虚拟主播直播解决方案

Build auto.js script development environment

Hengxing Ketong invites you to the 24th China expressway informatization conference and technical product exhibition in Hunan
随机推荐
The daily life of programmers
LeetCode(剑指 Offer)- 53 - I. 在排序数组中查找数字 I
Makefile+make Basics
Makefile+Make基础知识
leetcode 763. Partition Labels 划分字母区间(中等)
Update learning materials daily
iOS面试准备 - 其他篇
Detailed comparison of break and continue functions
Oracle insert data
Delete blank pages in word documents
Several simple and difficult OJ problems with sequential force deduction
论pyscript使用感想(实现office预览)
在线教育的推荐系统
spinning up安装完使用教程测试是否成功,出现Library“GLU“ not found和‘from pyglet.gl import *错误解决办法
Install the gym corresponding to mujoco in the spinning up tutorial, and the error mjpro150 is reported
WebRTC实现简单音视频通话功能
Mysql:The user specified as a definer (‘root‘@‘%‘) does not exist 的解决办法
Leetcode (Sword finger offer) - 53 - I. find the number I in the sorted array
Nail dialog text converted to pictures cannot be copied and pasted on the document
Vscode one click compilation and debugging