karaxuna
karaxuna

Reputation: 26940

Validation attributed is cached

I have following code in custom validation attribute called DateRange:

    private DateTime _minDate = DateTime.Today.AddYears(-100);
    private DateTime _maxDate = DateTime.MaxValue;

    // String representation of the Min Date (yyyy/MM/dd)
    public string Min
    {
        get { return FormatDate(_minDate, DateTime.Today.AddYears(-100)); }
        set { _minDate = value == "Today" ? DateTime.Today : ParseDate(value, DateTime.Today.AddYears(-100)); }
    }
    // String representation of the Max Date (yyyy/MM/dd)
    public string Max
    {
        get { return FormatDate(_maxDate, DateTime.MaxValue); }
        set { _maxDate = value == "Today" ? DateTime.Today : ParseDate(value, DateTime.MaxValue); }
    }

Then I write this attribute in metadata on some property of entity model like this:

[DateRange(Max = "Today")]
public string SomeDateProperty { get; set; };

I set breakpoint on Max property's getter. First time I open view, breakpoint is activated and DateTime.Today is got. Consequent refresh of the view does not activate breakpoint and old value is got. I think it's caching validation attribute. My question is: Is this because of caching? If it is, then how to disable it? Thanks in advance

Upvotes: 3

Views: 666

Answers (1)

eyeballpaul
eyeballpaul

Reputation: 1735

The constructor for the custom attributes only get hit once, no idea how to turn off any sort of caching. The way I got round this for my scenario, was to only deal with the date calculation in the "IsValid" Method.

I created a date in the past attribute, that needed the date to be in the past, but you could set how long in the past was valid.

public class DateInPastAttribute : ValidationAttribute
{
    private const string DefaultErrorMessage = "'{0}' must be in the past.";

    public int DaysInPastAllowed { get; set; }

    public DateInPastAttribute(int daysInPastAllowed)
        : base(DefaultErrorMessage)
    {
        this.DaysInPastAllowed = daysInPastAllowed;
    }

    public override bool IsValid(object value)
    {
        if (!(value is DateTime))
        {
            return true;
        }

        DateTime maxDate = DateTime.Now;
        DateTime minDate = maxDate.AddDays(this.DaysInPastAllowed * -1);

        DateTime dateValue = (DateTime)value;
        return
            minDate <= dateValue &&
            dateValue <= maxDate;
    }

    public override string FormatErrorMessage(string name)
    {
        return string.Format(CultureInfo.CurrentCulture, this.ErrorMessageString, name);
    }
}

You can then use it in your view model like this:

[DateInPast(365)]
public DateTime DateReceived { get; set; }

Which would allow a date to be entered within the last year. You could amend this for the scenario that you require.

Upvotes: 2

Related Questions