1

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!

8
  • 1
    Your parameter needs to be the name of the other property, not the actual value of the other property (and in your method you use reflection to get the value of the other property). I recommend reading The Complete Guide To Validation In ASP.NET MVC 3 - Part 2 to understand how to create a custom validation attribute Commented Aug 24, 2017 at 12:21
  • 2
    As a side note, using string for a property which appears to be either a date or a time is not appropriate. And your regex allows 90:80 which I assume is also not valid Commented Aug 24, 2017 at 12:25
  • @StephenMuecke Thanks for the link and the note. I'm reading the doc. Commented Aug 24, 2017 at 12:29
  • What is it that your actually wanting to validate here? If the values are supposed to be times as your property names suggest, then your properties should be TimeSpan, but its not clear what GoldTime means Commented Aug 24, 2017 at 12:31
  • @StephenMuecke I use GoldTime as a key to make sure that user needs to use the gold time with StartTime and EndTime. Otherwise, StartTime and EndTime would be ignore (no need to update to the database). Commented Aug 24, 2017 at 12:34

1 Answer 1

1

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;
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! I will try.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.