我正在开发一个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的用户输入,并且一切都相当容易。
我现在正试图在服务器端验证这个条件(从文件中大量加载用户),我不知道如何从视图外部或控制器中调用这些验证。
我觉得这可能是很多人必须尝试做的事情;我的谷歌可以这么弱吗?这不可能吗?除了使用ModelState在控制器代码中执行此操作,我别无选择吗?
我尝试使用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);
但这总是让我真实。我也试过使用反射,但无济于事(我的知识在那个区域太浅)。
答案 0 :(得分:3)
我很好奇这个行为,所以我研究了一下。属性和元数据类将对您的场景(从数据库生成的模型类代码)有所帮助,但考虑到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。
希望它有所帮助!