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.pswp.cn/news/914833.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/914833.shtml
英文地址,請注明出處:http://en.pswp.cn/news/914833.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

分區表設計:歷史數據歸檔與查詢加速

以下為分區表設計的核心實現方案與技術要點,綜合最新技術實踐整理:一、分區表核心機制與價值?物理存儲與邏輯分離?分區表通過預定義規則(如時間戳、ID范圍)將大表物理拆分為多個子表(分區),對…

下班倒計時

下班倒計時#include <stdio.h> #include <time.h> #include <unistd.h>void print_remaining_time(time_t now, time_t tar_time) {double diff difftime(tar_time, now);int hours (int)diff / 3600;int minutes ((int)diff % 3600) / 60;int seconds (…

Vue配置特性(ref、props、混入、插件與作用域樣式)

前言Vue提供了許多高級特性來增強組件開發的能力。本文將深入解析Vue中的ref屬性、props配置、混入(mixin)、插件開發以及scoped樣式等核心特性&#xff0c;通過實例演示它們的用法&#xff0c;并給出最佳實踐建議。一、ref屬性詳解1. ref基本用法ref用于給元素或子組件注冊引用…

解析力和清晰度區別

在視覺成像、光學設備或數字信號處理領域&#xff0c;清晰度和解析力是兩個相關但側重點不同的概念。它們都與“細節呈現”有關&#xff0c;但核心定義、影響因素和應用場景存在顯著區別。以下從定義、核心差異、聯系三個方面詳細說明&#xff1a; 一、核心定義清晰度&#xff…

Java網絡通信:UDP和TCP

一、UDP特點&#xff1a; 無連接不可靠&#xff1a;通信雙方不事先建立連接&#xff0c;直接發送數據。數據封裝&#xff1a;將數據封裝在64KB的數據包中&#xff0c;包含接收端的IP和端口。UDP通信模型&#xff1a; 模型比喻&#xff1a;以拋韭菜為例&#xff0c;發送端像拋韭…

Java行為型模式(狀態模式)實現方式與測試方法

一、狀態模式實現方式 核心結構 狀態接口&#xff08;State&#xff09;&#xff1a;定義狀態相關的行為方法。具體狀態類&#xff08;ConcreteState&#xff09;&#xff1a;實現狀態接口&#xff0c;封裝特定狀態下的邏輯。上下文類&#xff08;Context&#xff09;&#xff…

MISRA C-2012準則之標準C環境準則

目錄 1.標準C環境準則 錯誤示例1&#xff1a;未定義行為&#xff08;整數溢出&#xff09; 錯誤示例2&#xff1a;未指定行為&#xff08;函數調用順序&#xff09; 錯誤示例3&#xff1a;語言擴展&#xff08;GCC內置函數&#xff09; 錯誤示例4&#xff1a;關鍵未指定行…

26、鴻蒙Harmony Next開發:ArkTS并發(Promise和async/await和多線程并發TaskPool和Worker的使用)

目錄 異步并發 (Promise和async/await) Promise async/await 多線程并發 多線程并發模型 內存共享模型 Actor模型 TaskPool TaskPool運作機制 TaskPool注意事項 Concurrent裝飾器 裝飾器說明 裝飾器使用示例 TaskPool擴縮容機制 擴容機制 縮容機制 Worker Wo…

[IRF/Stack]華為/新華三交換機堆疊配置

堆疊的三大優勢 提高資源利用率&#xff0c;獲得更高的轉發性能、鏈路帶寬降低網絡規劃的復雜度、方便網絡的管理降低故障對業務的影響時間 堆疊的兩個需求 設備型號必須統一系統版本必須統一 華三堆疊案例&#xff1a;#### S6850_1 <H3C>sy [H3C]undo in en [H3C]sy SW…

融智興科技: RFID超高頻洗滌標簽解析

在紡織品租賃與管理領域&#xff0c;布草、工服、醫護織物等物品的流轉追蹤一直是運營管理的核心挑戰。傳統管理方式依賴人工計數與條碼掃描&#xff0c;存在效率低下、差錯率高、損耗嚴重等問題&#xff0c;尤其在工業洗滌環境下&#xff0c;紙質標簽易損壞、識別率低。融智興…

從平面到時空:地圖故事的時空敘事與沉浸式閱讀

朋友們&#xff0c;在工作中你是否也遇到過這些令人頭疼的挑戰&#xff1f;當項目匯報時總覺得表達不夠精彩&#xff0c;方案講解時聽眾總是一頭霧水&#xff0c;制作應急預案時更是無從下手&#xff1f;別擔心&#xff01;今天我要向大家介紹一個超級實用的解決方案——地圖故…

自動控制原理知識地圖:舵輪、路徑與導航圖

掌握自控原理的關鍵&#xff0c;在于看清那棵枝繁葉茂的“知識樹”——從根部的數學模型&#xff0c;到主干的分析方法&#xff0c;直至頂端的系統設計。作為一名自動化專業學生&#xff0c;你是否曾在深夜里面對勞斯判據和奈奎斯特圖感到深深的恐懼&#xff1f;作為初入行的工…

Flutter在Android studio運行出現Error: Entrypoint is not a Dart file

Flutter在Android studio運行出現Error: Entrypoint is not a Dart file

NE綜合實驗2:RIP 與 OSPF 動態路由精細配置及ACL訪問控制列表 電腦

NE綜合實驗2&#xff1a;RIP 與 OSPF 動態路由精細配置及ACL訪問控制列表 實驗拓撲圖實驗需求 1.按照圖示配置IP地址 2.按照圖示區域劃分配置對應的動態路由協議 3.在R7上配置dhcp服務器&#xff0c;能夠讓pc可以獲取IP地址 4.將所有環回?宣告進ospf中&#xff0c;將環回?7宣…

Kafka 控制器(Controller)詳解:架構、原理與實戰

目錄Kafka 控制器&#xff08;Controller&#xff09;詳解&#xff1a;架構、原理與實戰一、控制器的核心職責1. 元數據管理2. 分區狀態機3. 故障恢復4. 集群操作協調二、傳統 ZooKeeper 模式下的控制器1. 控制器選舉機制2. 控制器與 ZooKeeper 的交互3. 潛在問題三、KRaft 模式…

【C++基礎】#define vs constexpr:C++ 編譯期常量的雙雄對決(面試高頻考點 + 真題解析)

?在 C++ 面試中,#define與constexpr的對比堪稱 “元老級” 考點 —— 據統計,在 2023-2024 年的 C++ 工程師面試中,該知識點的出現頻率高達 72%,尤其是在字節跳動、騰訊、華為等企業的校招 / 社招中,幾乎是必問內容。? 這兩個語法元素都與 “編譯期常量” 相關,但背后卻…

k8s環境使用Operator部署Seaweedfs集群(上)

作者&#xff1a;閆乾苓 文章目錄前言4.1 前置條件4.2 部署seaweedfs-operator4.3 準備operator鏡像4.4 使用operator部署Seaweedfs集群4.4.1 部署StorageClass4.4.2 使用StorageClass預先創建PV前言 SeaweedFS Operator是一個Kubernetes Operator&#xff0c;用于自動化部署和…

Git CLI高危任意文件寫入漏洞(CVE-2025-48384)PoC已公開

Git CLI&#xff08;命令行界面&#xff09;中存在一個高危漏洞&#xff0c;攻擊者可利用該漏洞在Linux和macOS系統上實現任意文件寫入。目前該漏洞的概念驗證&#xff08;PoC&#xff09;利用代碼已公開。該漏洞編號為CVE-2025-48384&#xff0c;CVSS嚴重性評分為8.1分&#x…

前端開發中關于表單內容的使用和基礎知識

在前邊&#xff0c;我們已經寫過Web前端開發&#xff0c;Web前端開發&#xff0c;萬字詳細博文帶你HTML&#xff0c;CSS快速入門&#xff08;上篇&#xff09;和Web前端開發&#xff0c;一文帶你HTML&#xff0c;CSS快速入門&#xff08;下篇&#xff09;&#xff0c;使用近兩萬…

linux 安裝mysql保姆教程

安裝包下載地址: MySQL :: Download MySQL Community Server (Archived Versions) 解壓到安裝包&#xff1a; tar -zxvf mysql-5.7.36-linux-glibc2.12-x86_64.tar.gz 創建Mysql用戶組和用戶 groupadd mysql useradd -r -g mysql mysql 編譯安裝并初始化 進入/home/mysql/m…