前言

一年多没更新博客,上一次写此系列还是四年前,虽迟但到,没有承诺,主打随性,所以不存在断更,催更,哈哈,上一篇我们细究从请求到绑定详细原理,本篇则是探讨模型绑定细节,当一个问题产生到最终解决时,回过头我们整体分析其产生背景以及设计思路才能有所获。好了,废话不多说,我们开始模型绑定细节之旅。

问题产生

我们定义一个模型,然后进行查询请求,当然,此时我们在后台控制器Action方法上推荐明确使用查询特性即FromQuery接收,代码如下

public class UserAddress
{
public string Code { get; set; }
}
[ApiController]
[Route("api/[controller]/[action]")]
public class UserAddressController : ControllerBase
{
private readonly ILogger<UserAddressController> _logger; public UserAddressController(ILogger<UserAddressController> logger)
{
_logger = logger;
} [HttpGet]
public IActionResult Get([FromQuery] UserAddress address)
{
return Ok(address);
}
}

没任何毛病,接下来我们在定义用户地址类上增加一个属性,如下所示

public class UserAddress
{
public string Code { get; set; }
public string Address { get; set; }
}

值绑定不上,这是神马情况,这难道是官方的Bug吗,我们用6.0和7.0都是如此,毫无疑问,利用.NET 8.0依然是此等结果,问题来了,请稍加思考大概是什么原因,让我们继续往下分析

根因源码分析

通过前后对比我们可以初步分析到原因可能是二方面之一或者二者结合,其一,对象属性address和接收对象参数变量address不能相同(不区分大小写),其二,接受对象参数变量address和URL上的键名称address不能相同(不区分大小写)。我们暂且只能分析到这个地方,当然,我们一试便知,至于根因是什么,接下来我们只能去分析模型绑定源码,说到分析源码,可能有些童鞋不知从何开始,这里给出我们从0开始分析其根因的整个过程,以供需要的童鞋做参考哈。仅我个人看法,除非精通,否则必会经历一个过程,这是必然,所以不用怀疑任谁都不能立马找到大概源码在哪里,我们注意关注点分析,别看着看着跑偏了,既然是模型绑定而且是查询绑定,这是在了解基本原理或学习官网文档有所印象的前提下,先看这里

然后我们怎么开始呢,我们直接自定义实现一个查询字符串值绑定即将上述代码拷贝一份出来,比如有些是有依赖的等等,将其修改去掉等等处理,还是我们强调的关注点,最后我们还要添加自定义实现

   builder.Services.AddControllers(options =>
{
options.ValueProviderFactories.Insert(0, new QueryStringValueProviderFactory());
});

我们看到实际上值都已正确获取到,但实际上传过来的键应该是属性Code或者Address才对,同时我们发现在此实现中包含了一个是否包含前缀的方法,这好像貌似就是针对我们绑定的属性加上方法上的参数变量即address,所以我们断点一步步调试进入该方法具体实现

源码调试现在还是方便了很多,我们来到绑定源头即将ActionContext转换为ModelBindingContext,也就是调用具体绑定实现之前即相关参数绑定准备前夕,我们看到赋值给了模型绑定上下文中的模型名称即ModelName,我们猜测这就是增加的前缀,继续往下调试实际调用的绑定者是哪一个,我们看到实际使用的复杂对象绑定,框架内置实现了十几个绑定,ValueProvider只是其中后台接收最简单的参数类型或者直接接收请求上下文相关的预处理,大多都由ModelBinder来接收处理绑定到控制器方法上,调试源码并不是那么明朗,我们直接再自定义实现一个ComplexObjectModelBinderProvider,其具体ComplexObjectModelBinder有个方法BindPropertiesAsync,这是实际做相关处理的地方

/// <summary>
/// Create a property model name with a prefix.
/// </summary>
/// <param name="prefix">The prefix to use.</param>
/// <param name="propertyName">The property name.</param>
/// <returns>The property model name.</returns>
public static string CreatePropertyModelName(string? prefix, string? propertyName)
{
if (string.IsNullOrEmpty(prefix))
{
return propertyName ?? string.Empty;
} if (string.IsNullOrEmpty(propertyName))
{
return prefix ?? string.Empty;
} if (propertyName.StartsWith('['))
{
// The propertyName might represent an indexer access, in which case combining
// with a 'dot' would be invalid. This case occurs only when called from ValidationVisitor.
return prefix + propertyName;
} return prefix + "." + propertyName;
}

好了,到了这里我们只是知道了框架就是这么做的处理导致值绑定不上,问题又来了,请思考框架这么设计的初衷和思想是什么呢,框架为我们考虑了诸多场景。我们删除上述所有自定义实现, 框架以为我们想要达到如下绑定目的,但没曾想剑走偏锋,实际被我们钻了个空子,正所谓你以为的是你以为的并不是我以为的,然后一脸懵波

举一反三

还没完,继续开课,我们分析完整个前因后果后,我们终于明白了IValueProvider接口中所说的前缀具体指的是什么意思,然后对于前缀匹配使用二分法算法,同理,我们也不难看出,上述是对象绑定处理,在相同条件下,对于集合亦是如此。

总结

当进行查询操作时请求URL上的键名称若和后台接收参数变量名称相同且不区分大小写,框架以为我们想要使用接收参数变量作为前缀来绑定值,在相同等等条件下,对于集合亦是如此,除非我们自定义实现一套,否则我们万不可将其定义为相同名称,如此会导致值绑定不上。

翻译

搜索

复制

你所不知道的ASP.NET Core进阶系列(三)的更多相关文章

  1. 你所不知道的ASP.NET Core MVC/WebApi基础系列(一)

    前言 最近发表的EF Core貌似有点多,可别误以为我只专攻EF Core哦,私下有时间也是一直在看ASP.NET Core的内容,所以后续会穿插讲EF Core和ASP.NET Core,别认为你会 ...

  2. 你所不知道的ASP.NET Core MVC/WebApi基础系列 (一)

    转自博客:https://www.cnblogs.com/CreateMyself/p/9235968.html 前言 最近发表的EF Core貌似有点多,可别误以为我只专攻EF Core哦,私下有时 ...

  3. 你所不知道的ASP.NET Core MVC/WebApi基础系列(二)

    前言 好久没冒泡了,算起来估计有快半年没更新博客了,估计是我第一次停更如此之久,人总有懒惰的时候,时间越长越懒惰,但是呢,不学又不行,持续的惰性是不行dei,要不然会被时光所抛弃,技术所淘汰,好吧,进 ...

  4. 你所不知道的ASP.NET Core MVC/WebApi基础系列 (二)

    转自博客:https://www.cnblogs.com/CreateMyself/p/10604293.html 前言 本节内容,我们来讲讲.NET Core当中的模型绑定系统.模型绑定原理.自定义 ...

  5. Asp.Net Core 进阶(三)—— IServiceCollection依赖注入容器和使用Autofac替换它

    Asp.Net Core 提供了默认的依赖注入容器 IServiceCollection,它是一个轻量级的依赖注入容器,所以功能不多,只是提供了基础的一些功能,要实现AOP就有点麻烦,因此在实际工作当 ...

  6. 你所不知道的库存超限做法 服务器一般达到多少qps比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制

    你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...

  7. js值----你所不知道的JavaScript系列(6)

    1.数组 在 JavaScript 中,数组可以容纳任何类型的值,可以是字符串.数字.对象(object),甚至是其他数组(多维数组就是通过这种方式来实现的) .----<你所不知道的JavaS ...

  8. js类型----你所不知道的JavaScript系列(5)

    ECMAScirpt 变量有两种不同的数据类型:基本类型,引用类型.也有其他的叫法,比如原始类型和对象类型等. 1.内置类型 JavaScript 有七种内置类型: • 空值(null) • 未定义( ...

  9. 闭包----你所不知道的JavaScript系列(4)

    一.闭包是什么? · 闭包就是可以使得函数外部的对象能够获取函数内部的信息. · 闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. · 闭包就 ...

  10. 你真的会玩SQL吗?你所不知道的 数据聚合

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

随机推荐

  1. OpenLayers文档

    https://openlayers.org/en/latest/apidoc/module-ol_interaction_DragZoom-DragZoom.html#changed

  2. python实现在函数中捕获某个异常,然后将异常的具体信息写入error.txt文件中;

    在程序开发中,如果对某些代码的执行不能确定(程序语法完全正确) 可以增加try来捕获异常 try这个关键字来捕获异常try:尝试执行的代码except:出现错误的处理 def func(): try: ...

  3. 【故障公告】多年的故障老朋友又来了:数据库服务器 CPU 100%

    数据库服务器 CPU 100% 问题几乎每年都要来几次,从来都不事先打一声招呼,今年的第2次在我们正忙着会员救园的时候来了. 今天 13:35 首先收到我们自己的异常告警通知: Execution T ...

  4. 在 Visual Studio 2022 中使用文件对比

    在最新版本的 Visual Studio 2022 中,加入了新的功能特性--"文件对比". 在开发过程中,开发人员有时会需要比对文件差异,特别是代码文件,之前很多时候是借助版本控 ...

  5. 【升职加薪秘籍】我在服务监控方面的实践(8)-elasticsearch 性能监控与分析手段

    大家好,我是蓝胖子,之前讲了mysql,redis中间件的监控,今天我们再来看看另一个基础组件elasticsearch,如何对它进行监控,当你思考如何对一个组件进行监控时,四大黄金指标会告诉你答案, ...

  6. git命令和遇到的问题

    命令 1.快速关联/修改Git远程仓库地址 (1).删除本地仓库当前关联的无效远程地址,再为本地仓库添加新的远程仓库地址 git remote -v //查看git对应的远程仓库地址 git remo ...

  7. MySQL实战实战系列 01 基础架构:一条SQL查询语句是如何执行的?

    这是专栏的第一篇文章,我想来跟你聊聊 MySQL 的基础架构.我们经常说,看一个事儿千万不要直接陷入细节里,你应该先鸟瞰其全貌,这样能够帮助你从高维度理解问题.同样,对于 MySQL 的学习也是这样. ...

  8. JAVA中三种I/O框架——BIO、NIO、AIO

    一.BIO(Blocking I/O) BIO,同步阻塞IO模型,应用程序发起系统调用后会一直等待数据的请求,直至内核从磁盘获取到数据并拷贝到用户空间: 在一般的场景中,多线程模型下的BIO是成本较低 ...

  9. Oracle-判断表上存在高水位线

    表上高水位线:通常一个新建的表,1个8K的数据块存放100行记录,若表上经常插入删除操作,造成表的水位线很高.下面从发现高水位线的办法,及解决高水位的方法说起: 1.发现存在高水位线的表:查看字典表u ...

  10. MySQL系列之主从复制基础——企业高可用性标准、主从复制简介、主从复制前提(搭建主从的过程)、主从复制搭建、主从复制的原理、主从故障监控\分析\处理、主从延时监控及原因

    文章目录 0.企业高可用性标准 *** 0.1 全年无故障率(非计划内故障停机) 0.2 高可用架构方案 1. 主从复制简介 ** 2. 主从复制前提(搭建主从的过程) *** 3. 主从复制搭建(C ...