.NET Core Razor中如何将元数据/特性传递给视图模型
你的这种实现思路本身是没问题的——分离实体模型和视图模型,只把视图需要的字段放到视图模型里,这完全符合关注点分离的设计原则,能避免把实体的所有细节暴露给前端视图,也让视图层更聚焦于自身的展示需求。
但你遇到的问题也很典型:因为视图模型和实体模型是两个独立的类,实体上的数据注解(比如验证、显示相关的特性)不会自动"继承"到视图模型上,所以视图自然就丢失了原本的验证和显示提示功能。
针对这个问题,你可以用这几种方式解决:
手动复制必要的注解到视图模型
这是最直接的方式,把实体模型中与视图相关的注解(比如[Display]、[StringLength]、[DataType]等)复制到视图模型的对应属性上。比如你的视图模型里的TimeRequired可以改成这样:[StringLength(100, ErrorMessage = "Order Required Time should be a maximum of 100 characters")] [DataType(DataType.Text)] [Display(Name = "Required Time", Prompt = "Enter the Time this order is required by (Optional)", Description = "The Time this order is required by the customer")] public string TimeRequired { get; set; }这种方式简单直接,适合视图模型字段较少的场景,能精准控制每个字段的注解。
使用
MetadataType特性共享元数据
如果实体和视图模型有很多重复的注解,你可以创建一个共享的元数据类,把所有注解集中放在这里,然后让实体和视图模型都引用这个元数据类,避免重复编写。步骤如下:
- 创建元数据类:
public class SalesOrderMetadata { [Display(Name = "Sales Order ID", Description = "The internal ID for this Sales Order")] [Key] public int SalesOrderId { get; set; } [StringLength(100, ErrorMessage = "Order Required Time should be a maximum of 100 characters")] [DataType(DataType.Text)] [Display(Name = "Required Time", Prompt = "Enter the Time this order is required by (Optional)", Description = "The Time this order is required by the customer")] public string TimeRequired { get; set; } // 实体里的其他字段注解也可以放在这里 } - 修改实体模型,添加
MetadataType特性:[MetadataType(typeof(SalesOrderMetadata))] public class SalesOrder { // 实体的属性定义(不需要再写注解) public int SalesOrderId { get; set; } public string TimeRequired { get; set; } public string CustomerOrderNumber { get; set; } public string SpecialInstructions { get; set; } } - 修改视图模型,同样添加
MetadataType特性:[MetadataType(typeof(SalesOrderMetadata))] public class SalesOrder { public int SalesOrderId { get; set; } public string TimeRequired { get; set; } }
这样,视图模型里的字段会自动应用元数据类中的注解,同时你依然可以保持视图模型的简洁,只保留需要的字段。
- 创建元数据类:
需要注意的是,不管用哪种方式,都要确保视图模型只包含当前视图真正需要的字段——不要为了共享注解就把实体的所有字段都加到视图模型里,那样就违背了使用视图模型的初衷。
内容的提问来源于stack exchange,提问作者steve_c123
相关产品推荐
相关产品推荐

