Set RegularExpression Dynamically in Model

2019-07-20 18:53发布

问题:

I need to set RegularExpression Dynamically in Model.

I mean, I have stored RegularExpression in table and then I will store that value in one variable.

Now I want to supply that variable in Regular Express validation.

i.e

[RegularExpression(VariableValue, ErrorMessage = "Valid Phone is required")]

Something like

i.e

string CustomExpress = "@"^(\+|\d)(?:\+?1[-. ]?)?\(?([0-9]{2})\)?[-. ]?([0-9]{1})[-. ]?([0-9]{9})$" (from Database's table)

[RegularExpression(CustomExpress, ErrorMessage = "Valid Phone is required")]
public string Phone { get; set; }

回答1:

You have two options, either you create your own validation attribute or you make your whole model "validatable".

Option 1

public class RegexFromDbValidatorAttribute : ValidationAttribute
{
    private readonly IRepository _db;

    //parameterless ctor that initializes _db

    public override ValidationResult IsValid(object value, ValidationContext context)
    {
        string regexFromDb = _db.GetRegex();

        Regex r = new Regex(regexFromDb);

        if (value is string && r.IsMatch(value as string)){
            return ValidationResult.Success;
        }else{
            return new ValidationResult(FormatMessage(context.DisplayName));
        }
    }
}

Then on your model:

[RegexFromDbValidator]
public string Telephone {get; set;}

Option 2

public SomeModel : IValidatableObject
{
    private readonly IRepository _db;

    //don't forget to initialize _db in ctor

    public string Telephone {get; set;}

    public IEnumerable<ValidationResult> Validate(ValidationContext context)
    {

        string regexFromDb = _db.GetRegex();

        Regex r = new Regex(regexFromDb);

        if (!r.IsMatch(Telephone))
            yield return new ValidationResult("Invalid telephone number", new []{"Telephone"});
    }
}

Here's a good resource that explains how to create validation attributes

Here's an example of using IValidatableObject



回答2:

As Murali stated Data Annotation attributes values must be compile time constants.

If you want to perform dynamic validation based on other model values you can try with some kind of third party framework (e.g. Fluent Validation, it even can be integrated in ASP.NET's model validation too).



回答3:

I believe there might be a way to implement this by inheriting the IValidatableObject interface. Upon doing so whenever the ModelState gets validated on the server side you could perform all the necessary checks that you wish. It would look something like:

public class SomeClass: IValidatableObject {
    private RegEx validation;
    public SomeClass(RegEx val) {
        this.validation = val;
    }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var results = new List<ValidationResult>();
        // perform validation logic - check regex etc...
        // if an error occurs:
        results.Add(new ValidationResult('error message'));
    }
}