总之,我正在尝试在运行时基于数据库字段创建实例特定的数据注释属性。我现在所做的工作可以很好地创建初始模型,但当模型发布回来并进行服务器验证时就会失败。
(我在视图模型中的集合中使用了相同的输入模型,但必须对集合中的每个实例应用不同的验证……例如,输入的第一次出现可能被限制在1-100的范围内,但在同一输入页面上提示的同一模型的下一次出现将在1000-2000的范围内。另一个可能是日期,或者必须是6个字符长的字符串……)
我会解释我做了什么,我的问题在哪里:
我继承了DataAnnotationsModelMetadataProvider
,并提供了我自己的GetMetadataForProperty
实现(这与验证问题无关……)
我继承了DataAnnotationsModelValidatorProvider
,并提供了GetValidators
的facade实现。我想在这里做的是基于我的数据库记录创建新的属性,然后将这些属性传递给基本实现,从而相应地创建Validator。
然而。。。。。。在PROPERTY级别调用GetValidators
。。。。当用我想应用验证器的属性名称调用它时,我需要找到该属性名称的适用DB记录,这样我就可以找到我需要创建的属性。。。。但是。。。我无法仅从值字段的属性名称中获取DB记录的密钥。。。。。事实上,DB键在父模型中。。。。。那么我该如何掌握它呢?!
我尝试过使用一个静态变量(YUK),在调用一个属性的过程中存储密钥,并在另一次调用值字段属性时检索它。。。。但是,由于模型是单向串行化的,并且以相反的方式去串行化,我最终发现我的密钥与我所需的属性不同步。
为了增加一点复杂性,我还使用了一个自定义的模型活页夹。我已经按照这里其他地方的建议重写了CreateModel,但我找不到将元数据或附加值附加到输出模型的PROPERTY的方法。。。。仅限于模型本身。。。。但是我如何在GetValidators对PROPERTY的调用中获取MODEL元数据/附加值呢?
所以。。。。我的问题有两个。。。。。
1) 有人能帮我把我的数据库密钥从我的自定义模型绑定到我的ValidationProvider上的GetValidators方法吗?或者可能使用我的自定义元数据提供程序?
2) 有没有一种不同的、更简单的方法可以在运行时基于数据库记录创建验证器?
我认为这比它需要的要复杂得多。你只需要让你的验证标准选择器成为你的视图模型的一部分。它们不一定要展示(如果需要保存用于回邮目的,可以存储在隐藏处)。
然后你可以使用FluentValidation之类的东西来创建规则,比如
RuleFor(model => model.myprop)
.When(model => model.criteria == whatever)
.GreaterThan(100)
.LessThan(1000);
Where criteria是当您的属性必须在某个范围内时用于选择的任何值。
因此,这意味着您要构建视图模型,以包含用于选择验证规则的条件。
我也在FluentValidation论坛上问过这个问题,这里没有答案,也没有建议我不要使用Fluent,这让我找到了自己的解决方案(我知道这几乎肯定意味着我正在做一些非常糟糕/不寻常/不必要的事情!)
我最终所做的是在我的自定义模型绑定器的CreateModel方法中分配我的控制器静态变量,在那里我可以访问整个客户端模型,而不是试图通过自定义MetaDataProvider来完成。这似乎运行得很好,让我的应用程序达到了v1。
不过,我对这个解决方案并不满意,所以我将在未来几个月内对整个领域进行重构,所以我仍然很感激人们对如何以通用方式实现动态验证的任何其他意见/想法。
我知道这是一个老问题,但我回答这个问题是为了让许多其他人从中受益。
请参阅下面的文章,他们正在从xml 加载属性
从XML加载C#MVC.NET数据注释属性,表单验证
我认为你可以遵循同样的方法,而不是从xml中读取,你可以从数据库中读取,并根据模型数据类型动态添加这些规则
您也可以参考以下方法
DataAnnotations动态附加属性