I am playing around with The Enterprise Library Validation Block. I have a class from a Linq To Entities edmx file I am using in an MVC project. I want to make sure that a Nullable DateTime is always later than a DateTime. I am using attributes in a metadata class to create a default ruleset. When attempting to validate with the PropertyComparisonValidator I get the Exception:
A validation attribute of type PropertyComparisonValidatorAttribute cannot be used to validate values.
I theorized that I couldn't compare a Nullable type to a struct so I wrote the custom class below specifcally to get around that perceived problem. Still I get this exception:
A validation attribute of type NullableDateComparisonValidatorAttribute cannot be used to validate values.
Next I attempted Self Validation from the Enterprise Library and that failed to fire when validating. I am at a temporary standstill until I get this figured out. Please suggest a solution\workaround that isn't too ugly.
using System;
using System.Reflection;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
namespace IdahoUtility
{
public class NullableComparisonValidator<T> : Validator<Nullable<T>>
where T: struct, IComparable
{
protected string propertyToCompare { get; set; }
protected ComparisonOperator comparisionOperator { get; set; }
protected T TargetProperty(object currentTarget)
{
if (null == currentTarget)
{
throw new ArgumentNullException("currentTarget");
}
Type t = currentTarget.GetType();
PropertyInfo pInfo = t.GetProperty(propertyToCompare);
object oValue = pInfo.GetValue(currentTarget, null);
if (oValue.GetType() != typeof(T))
{
throw new InvalidOperationException(string.Format("Property compared must be a {0}!",typeof(T)));
}
return (T)oValue;
}
public NullableComparisonValidator(string PropertyToCompare, ComparisonOperator cmpOp)
:base(null,null)
{
if (string.IsNullOrWhiteSpace(PropertyToCompare))
{
throw new ArgumentException("PropertyToCompare is Invalid!", "PropertyToCompare");
}
propertyToCompare = PropertyToCompare;
comparisionOperator = cmpOp;
}
protected override void DoValidate(Nullable<T> objectToValidate, object currentTarget, string key, ValidationResults validationResults)
{
// ignore nulls
if (null == objectToValidate)
{
return;
}
switch (comparisionOperator)
{
case ComparisonOperator.Equal:
DoValidateEqual(objectToValidate, currentTarget, key, validationResults);
break;
case ComparisonOperator.GreaterThan:
DoValidateGreaterThan(objectToValidate, currentTarget, key, validationResults);
break;
case ComparisonOperator.GreaterThanEqual:
DoValidateGreaterThanEqual(objectToValidate, currentTarget, key, validationResults);
break;
case ComparisonOperator.LessThan:
DoValidateLessThan(objectToValidate, currentTarget, key, validationResults);
break;
case ComparisonOperator.LessThanEqual:
DoValidateLessThanEqual(objectToValidate, currentTarget, key, validationResults);
break;
case ComparisonOperator.NotEqual:
DoValidateNotEqual(objectToValidate, currentTarget, key, validationResults);
break;
}
}
private void DoValidateLessThanEqual(Nullable<T> objectToValidate, object currentTarget, string key, ValidationResults validationResults)
{
if (objectToValidate.Value.CompareTo(TargetProperty(currentTarget)) > 0)
{
LogValidationResult(validationResults, string.Format("Should be less than or equal to {0}!", propertyToCompare), currentTarget, key);
}
}
开发者_开发知识库 private void DoValidateLessThan(Nullable<T> objectToValidate, object currentTarget, string key, ValidationResults validationResults)
{
if (objectToValidate.Value.CompareTo(TargetProperty(currentTarget)) >= 0)
{
LogValidationResult(validationResults, string.Format("Should be less than {0}!", propertyToCompare), currentTarget, key);
}
}
private void DoValidateGreaterThanEqual(Nullable<T> objectToValidate, object currentTarget, string key, ValidationResults validationResults)
{
if (objectToValidate.Value.CompareTo(TargetProperty(currentTarget)) < 0)
{
LogValidationResult(validationResults, string.Format("Should be greater than or equal {0}!", propertyToCompare), currentTarget, key);
}
}
private void DoValidateGreaterThan(Nullable<T> objectToValidate, object currentTarget, string key, ValidationResults validationResults)
{
if (objectToValidate.Value.CompareTo(TargetProperty(currentTarget)) <= 0)
{
LogValidationResult(validationResults, string.Format("Should be greater than {0}!", propertyToCompare), currentTarget, key);
}
}
private void DoValidateEqual(Nullable<T> objectToValidate, object currentTarget, string key, ValidationResults validationResults)
{
if (objectToValidate.Value.CompareTo(TargetProperty(currentTarget)) != 0)
{
LogValidationResult(validationResults, string.Format("Should be equal to {0}!", propertyToCompare), currentTarget, key);
}
}
private void DoValidateNotEqual(Nullable<T> objectToValidate, object currentTarget, string key, ValidationResults validationResults)
{
if (objectToValidate.Value.CompareTo(TargetProperty(currentTarget)) == 0)
{
LogValidationResult(validationResults, string.Format("Should not be equal to {0}!", propertyToCompare), currentTarget, key);
}
}
protected override string DefaultMessageTemplate
{
get { return "{0}"; }
}
}
}
The problem had nothing to do with it being a nullable type. I ended up completely reworking the Validation. I removed the Metadata classes with attributes and moved my validation to configuration using the Enterprise Library tool. I was finally able to use a Property Comparison Validator to ensure that the end date followed the start date. The final snag was that I couldn't use the default Rule Set. I am using this in an ASP.NET MVC web site and I was able to make client side validation work using the Enterprise Library. I am actually very pleased with the whole thing even if it is unclear to me why the original set up did not work.
精彩评论