当前位置: 首页 > web >正文

aspnetcore Mvc配置选项中的ModelMetadataDetailsProviders

在ASP.NET Core 中,ModelMetadataDetailsProviders 是用于配置模型元数据提供程序的核心组件,它决定了如何解析和提供模型属性的元数据(如数据类型、验证规则、显示名称等)。以下是其详细解析:

一、核心概念与作用

  1. 模型元数据(ModelMetadata)

    • 描述模型属性的元数据信息,包括:
      • 数据类型(如intstring
      • 验证特性(如[Required][MaxLength]
      • 显示名称(如[Display(Name="用户名")]
      • 绑定源(如[FromForm][FromQuery]
  2. ModelMetadataDetailsProviders 的角色

    • 提供一个扩展点,允许注册多个元数据提供程序,按顺序处理并合并元数据。
    • 支持自定义元数据逻辑,例如从数据库、配置文件或其他数据源动态生成元数据。

二、内置的元数据提供程序

ASP.NET Core 默认包含以下主要的元数据提供程序:

提供程序类型作用描述
DataAnnotationsMetadataProviderDataAnnotations特性(如[Required][Display])中提取元数据。
ValidationMetadataProvider提供数据验证相关的元数据(如[Range][RegularExpression])。
BindingMetadataProvider提供绑定相关的元数据(如[BindRequired][FromQuery])。
ConventionsMetadataProvider应用约定(Conventions)定义的元数据(如控制器 / 动作选择规则)。

三、自定义元数据提供程序

1. 实现 IModelMetadataDetailsProvider 接口
public class CustomMetadataProvider : IModelMetadataDetailsProvider
{public void CreateBindingMetadata(BindingMetadataProviderContext context){// 自定义绑定元数据(如设置默认绑定源)if (context.Key.Name == "Email"){context.BindingMetadata.BindingSource = BindingSource.Query;}}public void CreateDisplayMetadata(DisplayMetadataProviderContext context){// 自定义显示元数据(如修改显示名称)if (context.Key.Name == "UserName"){context.DisplayMetadata.DisplayName = () => "用户昵称";}}public void CreateValidationMetadata(ValidationMetadataProviderContext context){// 自定义验证元数据(如添加额外验证规则)if (context.Key.Name == "Age"){context.ValidationMetadata.ValidatorMetadata.Add(new RangeAttribute(18, 100) { ErrorMessage = "年龄必须在18-100岁之间" });}}
}
2. 注册自定义提供程序

Startup.ConfigureServices中注册:

services.AddControllersWithViews(options =>
{// 插入自定义元数据提供程序(优先级高于默认提供程序)options.ModelMetadataDetailsProviders.Add(new CustomMetadataProvider());
});

四、应用场景示例

1. 动态显示名称

从数据库或配置文件获取属性的显示名称,而非硬编码在[Display]特性中:

public class DatabaseDisplayMetadataProvider : IModelMetadataDetailsProvider
{private readonly IConfiguration _config;public DatabaseDisplayMetadataProvider(IConfiguration config){_config = config;}public void CreateDisplayMetadata(DisplayMetadataProviderContext context){// 从数据库或配置中获取显示名称var displayName = _config[$"DisplayNames:{context.Key.Name}"];if (!string.IsNullOrEmpty(displayName)){context.DisplayMetadata.DisplayName = () => displayName;}}// 其他方法实现...
}
2. 基于角色的验证规则

根据用户角色动态调整验证规则:

public class RoleBasedValidationProvider : IModelMetadataDetailsProvider
{private readonly IHttpContextAccessor _httpContextAccessor;public RoleBasedValidationProvider(IHttpContextAccessor httpContextAccessor){_httpContextAccessor = httpContextAccessor;}public void CreateValidationMetadata(ValidationMetadataProviderContext context){var user = _httpContextAccessor.HttpContext.User;// 管理员角色放宽验证if (user.IsInRole("Admin") && context.Key.Name == "Price"){context.ValidationMetadata.ValidatorMetadata.Clear(); // 移除所有验证}}// 其他方法实现...
}

五、执行顺序与优先级

  • 元数据提供程序按注册顺序执行,后注册的提供程序可以覆盖前面的元数据。
  • 示例:先应用默认提供程序,再应用自定义提供程序:
options.ModelMetadataDetailsProviders.Add(new CustomMetadataProvider()); // 后执行,优先级高
options.ModelMetadataDetailsProviders.Insert(0, new AnotherProvider());  // 先执行,优先级低

六、内置的元数据提供程序

  ExcludeBindingMetadataProvider 是一个内置的元数据提供程序,用于排除特定类型或属性的模型绑定。你提供的代码 options.ModelMetadataDetailsProviders.Add(new ExcludeBindingMetadataProvider(typeof(IModelStateService))); 的作用是阻止控制器参数绑定到 IModelStateService 类型的属性。

  1. 阻止模型绑定
    当你注册 ExcludeBindingMetadataProvider 并指定某个类型(如 IModelStateService)时,ASP.NET Core 会:

    • 忽略 HTTP 请求中与该类型相关的数据(如表单字段、查询字符串)。
    • 防止该类型的属性被模型绑定器填充值。
  2. 实现机制
    ExcludeBindingMetadataProvider 通过修改元数据中的 BindingMetadata.IsBindingAllowed 属性为 false,告诉模型绑定器跳过该类型的属性。

  3. 排除服务接口的绑定

    如果你在控制器中注入了服务(如 IModelStateService),但不想让它被请求数据绑定:
    public class MyController : Controller
    {private readonly IModelStateService _service;// 构造函数注入服务(但不希望从请求中绑定)public MyController(IModelStateService service){_service = service;}[HttpPost]public IActionResult Submit([FromForm] MyModel model){// 使用_service处理业务逻辑_service.Validate(model);return Ok();}
    }

            通过 ExcludeBindingMetadataProvider 排除 IModelStateService,可防止攻击者通过请求参数伪造服务实例。

  4. 排除敏感属性的绑定

如果你有一个包含敏感字段(如 IsAdminPasswordHash)的模型,可排除这些属性的绑定:
// 全局排除IsAdmin属性的绑定
options.ModelMetadataDetailsProviders.Add(new ExcludeBindingMetadataProvider("IsAdmin"));
这比在每个模型属性上添加 [BindNever] 特性更高效。

七、与其他组件的关系

组件与 ModelMetadataDetailsProviders 的关系
ModelBinder使用元数据确定如何绑定数据(如类型转换、绑定源)。
DataAnnotations元数据提供程序会解析DataAnnotations特性并生成对应元数据。
ModelValidator使用元数据中的验证规则执行模型验证。
Razor 视图通过元数据获取属性的显示名称、验证消息等,用于生成 HTML 标签(如asp-for)。

八、注意事项

  1. 性能考量
    避免在元数据提供程序中执行耗时操作(如数据库查询),可考虑缓存策略。

  2. 线程安全
    元数据提供程序实例通常是单例的,确保实现线程安全。

  3. 与 DataAnnotations 的兼容性
    自定义提供程序应与DataAnnotations特性协同工作,而非完全替代。

  4. 元数据缓存
    框架会缓存元数据,修改模型类后需重启应用才能生效。

总结

ModelMetadataDetailsProviders 是ASP.NET Core 中扩展模型元数据的强大机制,通过自定义元数据提供程序,你可以:

  • 动态生成显示名称、验证规则等元数据。
  • 基于运行时条件(如用户角色、配置)调整元数据。
  • 整合外部数据源(如数据库、配置文件)的元数据。

合理使用这一机制,可以实现更灵活、更动态的模型元数据管理,提升应用的可扩展性和可维护性。

http://www.xdnf.cn/news/15482.html

相关文章:

  • Ubuntu服务器安装Miniconda
  • 鸿蒙应用开发: 鸿蒙项目中使用私有 npm 插件的完整流程
  • 华为MateBook D 16 SE版 2024款 12代酷睿版i5集显(MCLF-XX,MCLF-16)原厂OEM预装Win11系统
  • vscode 打开项目时候,有部分外部依赖包找不到定义或者声明,但是能使用cmake正常编译并且运行
  • 【前端】【Iconify图标库】【vben3】createIconifyIcon 实现图标组件的自动封装
  • AWS RDS PostgreSQL可观测性最佳实践
  • Linux操作系统从入门到实战(八)详细讲解编译器gcc/g++编译步骤与动静态库链接
  • S7-1200 中 AT 覆盖参数的应用:灵活访问数据区域的实用指南
  • 银河麒麟KYSEC安全机制详解
  • Java设计模式(java design patterns)
  • 【linux V0.11】boot
  • 【算法深练】BFS:“由近及远”的遍历艺术,广度优先算法题型全解析
  • 掉线监测-tezos rpc不能用,改为残疾网页监测
  • 视频孪生与三维融合:智汇云舟赋能智慧化电力转型的破局之道
  • 【数据结构初阶】--单链表(二)
  • Flask服务器公外网访问,IPv6(亲测有效!!!!)
  • 哈希扩展 --- 海量数据处理
  • 20250714让荣品RD-RK3588开发板在Android13下长按关机
  • 【Linux】Jenkins Lts 配置构建 Maven 项目
  • 机床自动化中的“方言翻译官”:EtherNet/IP 转 PROFIBUS DP 实战手记
  • 3分钟搭建自动签到打卡RPA程序:验证码自动识别
  • 知识蒸馏:模型压缩与知识迁移的核心引擎
  • C++--unordered_set和unordered_map的使用
  • CCF-GESP 等级考试 2025年6月认证Python三级真题解析
  • EVOLVEpro安装使用教程-蛋白质语言模型驱动的快速定向进化
  • 2025年渗透测试面试题总结-2025年HW(护网面试) 45(题目+回答)
  • [Dify]-基础入门8- 使用 Dify 创建文档问答机器人(零代码实现)
  • openeuler使用桥接模式(包括新建虚拟机和已有虚拟机)
  • 【读书笔记】《C++ Software Design》第十章与第十一章 The Singleton Pattern The Last Guideline
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | ToastNotification(推送通知)