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

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.dtcms.com/a/279759.html

相关文章:

  • SAP-ABAP:SAP库存管理核心增强:IF_EX_MB_DOCUMENT_BADI 深度解析
  • 交换类排序的C语言实现
  • Hello, Tauri!
  • 基于Android的景点旅游信息系统App
  • 使用aiohttp实现高并发爬虫
  • uni-app开发的页面跳转全局加载中
  • 基于HarmonyOS的智能灯光控制系统设计:从定时触发到动作联动全流程实战
  • C++ 中常见的字符串定义方式及其用法
  • 1111自己
  • 基础分类模型及回归简介(一)
  • 体验RAG GitHub/wow-rag
  • 前端同学,你能不能别再往后端传一个巨大的JSON了?
  • 引用(C++)
  • python的微竞网咖管理系统
  • ⽂本预处理(一)
  • volatile 关键字
  • Codeforces Round 787 (Div. 3)(A,B,C,D,E,F,G)
  • DO,VO,DTO.....
  • (二十四)-java+ selenium自动化测试-三大延时等待
  • UI前端与数字孪生融合案例:智慧城市的智慧停车引导系统
  • 苍穹外卖Day4
  • JavaScript进阶篇——第二章 高级特性核心
  • vue笔记4 vue3核心语法和pinia基础使用
  • 【leetcode】326. 3的幂
  • VSCode中使用容器及容器编排docker-compose
  • L1与L2正则化详解:原理、API使用与实践指南
  • FastAPI + gRPC 全栈实践:Windows 开发到 Ubuntu 部署全指南
  • JVM监控及诊断工具-命令行篇
  • ubuntu 22.04 anaconda comfyui安装
  • 8.数据库索引