asp.net-coreblazor

Is there a way to have dynamic regex strings in a RegularExpression attribute?


The textbox on my Blazor app is being validated using a [RegularExpression] attribute. This attribute needs to be dynamic, in that I need to be able to change the validation string "on the fly". I have working code that can change the string inside the attribute, but when the validation occurs, the new string is reset back to the original string. Debugging the code shows that the attribute's constructor is being called during the validation event which resets back to the original validation string. Does anyone have any ideas on how to remedy this issue? I can provide the code if needed.

TIA

Regarding Yogi's reply about it being readonly, I had forgotten to mention that I used a derived class from ValidationAttribute (not my code), that has an Update method to set the new pattern. The code works - with the debugger I can examine the pattern property to see the new value. I suspect that the <DataAnnotationsValidator/> is re-instantiating the class which is resetting the original pattern value.


Solution

  • After testing , yes the attribute reinitializes a new instance and thus the pattern value always turns to the origin one. Since I cannot stop the attribute instance from being reinitialized, I have another solution which is to adding a property in model to control the pattern.

    Model

    public class MyModel
    {
        public string ValidationPattern { get; set; } = "^[a-zA-Z]+$"; // Initial pattern
    
        [DynamicRegexValidation(nameof(ValidationPattern), ErrorMessage = "Wrong Input")]
        public string MyTextBox { get; set; }
    }
    

    DynamicRegexValidationAttribute

    public class DynamicRegexValidationAttribute : ValidationAttribute
    {
        public string PatternPropertyName { get; }
    
        public DynamicRegexValidationAttribute(string patternPropertyName)
        {
            PatternPropertyName = patternPropertyName;
        }
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value == null)
            {
                return ValidationResult.Success;
            }
    
            var patternProperty = validationContext.ObjectType.GetProperty(PatternPropertyName);
            var pattern = patternProperty.GetValue(validationContext.ObjectInstance) as string;
    
            if (!Regex.IsMatch(value.ToString(), pattern))
            {
                return new ValidationResult(ErrorMessage ?? "Invalid format based on the current pattern.");
            }
    
            return ValidationResult.Success;
        }
    }
    

    DynamicValidation component

    @page "/dynamic-validation"
    @using BlazorApp1.Models
    
    <h1>Dynamic Validation</h1>
    
    <EditForm Model="@model" OnValidSubmit="@HandleValidSubmit">
        <DataAnnotationsValidator />
        <ValidationSummary />
        <div class="mb-3">
            <label for="textInput">Text Input</label>
            <InputText id="textInput" @bind-Value="@model.MyTextBox" class="form-control" />
            <ValidationMessage For="@(() => model.MyTextBox)" />
        </div>
    
        <button type="button" class="btn btn-primary" @onclick="UpdateToNumbers">Change Pattern To Numbers)</button>
        <button type="button" class="btn btn-secondary" @onclick="UpdateToLetters">Change Pattern To Letters)</button>
        <button type="submit" class="btn btn-success">Submit</button>
    </EditForm>
    
    @if (!string.IsNullOrEmpty(output))
    {
        <div class="alert alert-success mt-3">@output</div>
    }
    
    @code {
        private MyModel model = new MyModel();
        private string output;
    
        private void UpdateToNumbers()
        {
            model.ValidationPattern = "^[0-9]+$";
        }
    
        private void UpdateToLetters()
        {
            model.ValidationPattern = "^[a-zA-Z]+$";
        }
    
        private void HandleValidSubmit()
        {
            output = "Submitted successfully";
        }
    }
    

    letter clicked :

    enter image description here

    number clicked

    enter image description here