Skip to content

服务器托管,北京服务器托管,服务器租用-价格及机房咨询

Menu
  • 首页
  • 关于我们
  • 新闻资讯
  • 数据中心
  • 服务器托管
  • 服务器租用
  • 机房租用
  • 支持中心
  • 解决方案
  • 联系我们
Menu

你所不知道的ASP.NET Core进阶系列(三)

Posted on 2023年11月20日2023年11月20日 by hackdl

前言

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

问题产生

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

public class UserAddress
{
    public string Code { get; set; }
}
[ApiController]
[Route("api/[controller]/[action]")]
public class UserAddressController : ControllerBase
{
    private readonly ILogger _logger;

    public UserAddressController(ILogger 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,这是实际做相关处理的地方

/// 
/// Create a property model name with a prefix.
/// 
/// The prefix to use.
/// The property name.
/// The property model name.
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上的键名称若和后台接收参数变量名称相同且不区分大小写,框架以为我们想要使用接收参数变量作为前缀来绑定值,在相同等服务器托管网等条件下,对于集合亦是如此,除非我们自定义实现一套,否则我们万不可将其定义为相同名称,如此会导致值绑定不上。

翻译

搜索

复制

服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net

相关推荐: Java8新特性1——函数式接口&lambda表达式
Java8新特性1——函数式接口&lambda表达式

Java8新特性1——函数式接口&lambda表达式 注:以下内容基于Java 8,所有代码都已在Java 8环境下测试通过 目录: Java8新特性1——函数式接口&lambda表达式 方法引用 Stream 1. 函数式接口 如果在一个接口…

Related posts:

  1. 北京上地软件园机房托管
  2. 福州服务器托管规定文件解析
  3. 多语种平行语料数据,助力“一带一路”深入交流
  4. 哈尔滨服务器托管的资格标准
  5. 高效稳定的服务器网站托管方案

服务器托管,北京服务器托管,服务器租用,机房机柜带宽租用

服务器托管

咨询:董先生

电话13051898268 QQ/微信93663045!

上一篇: docker安装及安装redis
下一篇: 【广州华锐互动】塔吊多人安拆VR互动培训系统

最新更新

  • 如何使用Python进行数据可视化
  • 鸿蒙原生应用/元服务开发-AGC分发如何生成密钥和和证书请求文件
  • 亚马逊云科技CEO接受采访,在re:Invent大会前剧透了一些干货
  • 基于 eBPF 构建下一代智能可观测系统
  • 【好文转载】曲线的切向量怎么求?和平面法向量的联系

随机推荐

  • 解析托管服务器工资:管理费用与效益的平衡
  • 解析idc机房机器托管费用构成因素
  • 探究三线接入机房的功能与优势
  • 优秀服务器托管协议书写指南
  • 网站服务器托管收费解析

客服咨询

  • 董先生
  • 微信/QQ:93663045
  • 电话:13051898268
  • 邮箱:dongli@hhisp.com
  • 地址:北京市石景山区重聚园甲18号2层

友情链接

  • 服务器托管
  • 机房租用托管
  • 服务器租用托管
©2023 服务器托管,北京服务器托管,服务器租用-价格及机房咨询 京ICP备13047091号-8