In summary, I'm trying to create instance-specific data-annotation attributes at runtime, based on database fields. What I have now works fine for creating the initial model, but falls over when the model is posted-back and the server-validation happens.

(I have the same input model being used in a collection within a viewmodel, but different validation must be applied to each instance in the collection....for example the first occurrence of the input may be restricted to a range of 1-100 but the next occurrence of the same model, prompted for on the same input page, would be a range of 1000-2000. Another may be a date, or a string that has to be 6 characters long.......)

I'll explain what I've done and where my issues are:

I've inherited DataAnnotationsModelMetadataProvider and provided my own implementation of GetMetadataForProperty (This doesn't have any bearing on the validation problem....yet)

I've inherited DataAnnotationsModelValidatorProvider and provided a facade implementation of GetValidators. What I want to do here is create new attributes based on my database-records and then pass those attributes through to the base implementation so the Validators are created accordingly.

However...... GetValidators is called at a PROPERTY level....When it is called with a propertyname that I want to apply validators to, I need to find the applicable DB record for this propertyname so I can find out what attributes I need to create....BUT...I can't get the DB record's key from just a propertyname of the value field.....In fact, the DB key is in the parent model.....So how do I get hold of it?!

I've tried using a static variable (YUK) and storing the key during a call for one property, and retrieving it during another call for my value field property....But because the model is serialised one-way and deserialised the opposite way I end up with my key being out-of-sync with my required attributes.

To add a slight complication I'm also using a custom model binder. I've overridden CreateModel as advised elsewhere on here, but I can't find a way of attaching metadata or additionalvalues to a PROPERTY of my output model....Only to the model itself....but how do I get at MODEL metadata/additionalvalues inside the GetValidators call for a PROPERTY ?

So....My question is twofold.....

1) Can anyone help me get my database-key from my custom-Model-binder to my GetValidators method on my ValidationProvider? Or maybe using my custom Metadata provider?

2) Is there a different, simpler, way of creating validators at runtime based on database records?

有帮助吗?

解决方案 2

I'd asked this on the FluentValidation forums also and the lack of answers here as well as the advice against using Fluent from there led me to find my own solution (I understand this almost certainly means I'm doing something really bad / unusual / unnecessary!)

What I've ended up doing is assigning my controller static variable in my Custom Model Binder's CreateModel method, where I have access to the entire client model, rather than trying to do it through a custom MetaDataProvider. This seems to work just fine and gets me towards v1 of my app.

I'm not really happy with this solution though so will look to refactor this whole area in the coming months so would still appreciate any other comments / ideas people have about how to implement dynamic validation in a generic way.

其他提示

I think you are making this far more complicated than it needs to be. You just need to make whatever your validation criteria selectors are part of your view model. They don't necessarily have to be displayed (they can be stored in hiddens if they need to be kept for postback purposes).

Then you can use something like FluentValidation to create rules that say

RuleFor(model => model.myprop)
   .When(model => model.criteria == whatever)
   .GreaterThan(100)
   .LessThan(1000);

Where criteria is whatever value you use to select when your property has to be in a certain range.

So that would mean you build your view model to include the criteria that is used for validation rule selection.

I know this is an old question, but I am answering this so that many others can be benefited from this.

Please see the below article where they are loading the attributes from an xml

Loading C# MVC .NET Data Annotation Attributes From XML, Form Validation

I think you can follow the same approach and instead of reading from xml you can read from database and add these rules dynamically based on the model data type

You can refer the below approach also

DataAnnotations dynamically attaching attributes

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top