user7739271
user7739271

Reputation:

Passing parameter to a custom validation attribute in ASP.NET MVC

I'm using ASP.NET MVC and I wanna create a custom validation attribute to validate StartTime and EndTime which refer from the text inputs.

I have tried:

Model:

public class MyModel
{
    public bool GoldTime { get; set; }

    [TimeValidation(@"^\d{1,2}:\d{1,2}$", GoldTime, ErrorMessage = "Start time is invalid.")]
    public string StartTime { get; set; }

    [TimeValidation(@"^\d{1,2}:\d{1,2}$", GoldTime, ErrorMessage = "End time is invalid.")]
    public string EndTime { get; set; }
}

Validation attribute:

public class TimeValidationAttribute : ValidationAttribute
{
    private readonly string _pattern;
    private readonly bool _useGoldTime;

    public TimeValidationAttribute(string pattern, bool useGoldTime)
    {
        _pattern = pattern;
        _useGoldTime = useGoldTime;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (_useGoldTime)
        {
            var regex = new Regex(_pattern);

            if (!regex.IsMatch(value.ToString()))
            {
                return new ValidationResult(ErrorMessage);
            }
        }

        return ValidationResult.Success;
    }
}

But I'm getting this error message:

An object reference is required for the non-static field, method, or property 'MyModel.GoldTime'

Then, I've tried again by changing GoldTime (in the model) to true, the error message would disappear.

So, my question is: How can I pass the parameter GoldTime to the attribute constructor? I need to use the GoldTime as a key to enable validating the value of StartTime and EndTime.

Thank you!

Upvotes: 1

Views: 3538

Answers (1)

Brian Mains
Brian Mains

Reputation: 50728

It is complaining about using a model property within the attribute definition. Instead, within your custom attribute, you can use properties on the ValidationContext class to get the underlying model, I think via validationContext.ObjectInstance.

Obviously, you don't want to hard-code the type of model but you could use reflection:

bool goldTime;
var prop = validationContext.ObjectInstance.GetType().GetProperty("GoldTime");
if (prop != null)
   goldTime = (bool)prop.GetValue(validationContext.ObjectInstance, null);

Or, define an interface for the model:

public interface ITimeModel
{
   bool GoldTime { get; set; }
}

And look for that:

bool goldTime;
if (validationContext.ObjectInstance is ITimeModel)
  goldTime = ((ITimeModel)validationContext.ObjectInstance).GoldTime;

Upvotes: 1

Related Questions