c# - 使用 Controller 或 View 外部的元数据验证对象

标签 c# asp.net asp.net-mvc validation asp.net-mvc-4

我正在开发一个 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/

相关文章:

c# - HttpWebResponse 超时

c# - 源 C dll 中是否需要 dllexport 才能通过 [DllImport] 在 C# 中使用?

c# - 不明确的调用 asp.net mvc 操作方法

asp.net - MVC3 应用程序忽略 Razor .cshtml 扩展名

javascript - 如何使用 HTML 图像请求将数据发送到服务器,或返回数据作为响应

asp.net - EntityFramework.dll 中发生了 'System.Data.Entity.Infrastructure.DbUpdateException' 类型的异常,但未在用户代码中处理

c# - 如何在边框后绑定(bind)我的文本?

c# - 在触发器中进行否定的最简单方法是什么?

c# - 无法将类型 System.web.mvc.JsonResult 隐式转换为 System.Generic.IEnumerable

asp.net-mvc - 支持多语言的ASP MVC技术