我正在开发一个 ASP.NET MVC4 Web 应用程序,特别是在一个非常典型的 CRUD 界面中。
我有一个这样的模型类:
[MetadataType(typeof(USER_Metadata))]
public partial class USER
{
public class USER_Metadata
{
[Required(ErrorMessageResourceName = "MISSING_EMAIL", ErrorMessageResourceType = typeof(Resources.General.Usuario))]
[StringLength(70, MinimumLength = 3,
ErrorMessageResourceName = "EMAIL_LENGTH_ERROR", ErrorMessageResourceType = typeof(Resources.General.Usuario))]
[DataType(DataType.EmailAddress)]
public string EMAIL { get; set; }
/* other, similarly annotated members */
}
public string EMAIL { get; set; }
}
我认为这是 MVC 中使用的模型类的相当标准的定义。我使用该元数据来验证 ViewPage 中的用户输入,一切都相当简单。
我现在正在尝试在服务器端验证此条件(以从文件中大量加载用户),并且我不知道如何从 View 或 Controller 外部调用这些验证。
我觉得这可能是很多人都尝试过的事情;我的谷歌搜索能这么弱吗?难道不可能吗?除了使用 ModelState 在 Controller 代码中执行此操作之外,我别无选择吗?
我尝试使用 Validator,我认为这是最明显的方式:
var validationResults = new List<System.ComponentModel.DataAnnotations.ValidationResult>();
var isValid = Validator.TryValidateObject(
instance: user,
validationContext: new ValidationContext(user, serviceProvider: null, items: null),
validationResults: validationResults,
validateAllProperties: true);
但这总是给我真实的感觉。我也尝试过使用反射,但没有成功(我在这方面的知识太浅)。
最佳答案
我对这种行为很好奇,所以我做了一些研究。属性和元数据类将对您的场景有所帮助(从数据库生成的模型类代码),但请考虑到 USER
不会继承 USER_Metadata
中的元数据,除了 MetadataType
属性之外,这些类之间没有任何链接。由验证代码来解释它!
不幸的是,Validator
类似乎不尊重 [MetadataType]
属性,因此您需要手动注册自己。我发现它在这个SO question中有解释。所以这是一个只要有元数据类就会出现的问题,无论是否嵌套都没有关系。
根据该答案,您可以使用以下行注册元数据类(按照原始示例,使用 USER
类和嵌套的 USER_Metadata
元数据类):
TypeDescriptor.AddProviderTransparent(
new AssociatedMetadataTypeTypeDescriptionProvider(typeof(USER), typeof(USER.USER_Metadata)), typeof(USER));
快速而肮脏的方法是确保在验证对象之前调用该行,如下所示:
TypeDescriptor.AddProviderTransparent(
new AssociatedMetadataTypeTypeDescriptionProvider(typeof(USER), typeof(USER.USER_Metadata)), typeof(USER));
var validationResults = new List<System.ComponentModel.DataAnnotations.ValidationResult>();
var isValid = Validator.TryValidateObject(
instance: user,
validationContext: new ValidationContext(user, serviceProvider: null, items: null),
validationResults: validationResults,
validateAllProperties: true);
但是,您可以编写一些反射代码并在程序集中注册所有元数据类,作为应用程序初始化的一部分。类似的代码已经写在 this other SO question 中.
希望对你有帮助!
关于c# - 使用 Controller 或 View 外部的元数据验证对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21707323/