Skip to content

Instantly share code, notes, and snippets.

@vanillajonathan
Created June 26, 2017 12:59
Show Gist options
  • Save vanillajonathan/2c473c7ae7acd0249ccfcac0d3a7de97 to your computer and use it in GitHub Desktop.
Save vanillajonathan/2c473c7ae7acd0249ccfcac0d3a7de97 to your computer and use it in GitHub Desktop.
Ensures that the end date is not prior to the start date.
using System;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using System.Reflection;
namespace DataAnnotations
{
/// <summary>
/// Provides an attribute that compares two properties of a model and
/// ensures that the value of the end property is not prior to the value
/// of the begin property.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class NotBeforeAttribute : ValidationAttribute
{
private const string NotBefore = "'{0}' can not be before '{1}'.";
private const string UnknownProperty = "Could not find a property named {0}.";
private string _otherProperty;
private string _otherPropertyDisplayName;
/// <summary>
/// Initializes a new instance of the <see cref="NotBeforeAttribute"/> class.
/// </summary>
/// <param name="otherProperty">The property to compare with the current property.</param>
public NotBeforeAttribute(string otherProperty) : base(NotBefore)
{
_otherProperty = otherProperty ?? throw new ArgumentNullException(nameof(otherProperty));
}
public override bool RequiresValidationContext => true;
public override string FormatErrorMessage(string name)
{
return string.Format(CultureInfo.CurrentCulture, ErrorMessageString, name,
_otherPropertyDisplayName ?? _otherProperty);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var otherPropertyInfo = validationContext.ObjectType.GetRuntimeProperty(_otherProperty);
if (otherPropertyInfo == null)
{
return new ValidationResult(string.Format(CultureInfo.CurrentCulture, UnknownProperty, _otherProperty));
}
object otherPropertyValue = otherPropertyInfo.GetValue(validationContext.ObjectInstance, null);
if ((dynamic)value < (dynamic)otherPropertyValue)
{
if (_otherPropertyDisplayName == null)
{
_otherPropertyDisplayName = GetDisplayNameForProperty(validationContext.ObjectType, otherPropertyInfo);
}
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
return null;
}
private string GetDisplayNameForProperty(Type containerType, PropertyInfo property)
{
var attributes = CustomAttributeExtensions.GetCustomAttributes(property, true);
var display = attributes.OfType<DisplayAttribute>().FirstOrDefault();
if (display != null)
{
return display.GetName();
}
return _otherProperty;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment