0

I've created a custom data annotation which works as expected on the client-side, correctly displaying a custom message to the user when the date entered is invalid. However, if the entry fails server-side validation, the default error message is returned. I'm unable to get to the root of why the custom message is not also displayed when failing server-side validation. Stepping through, everything seems fine in the debugger, but the output is ultimately incorrect. Any help would be much appreciated!

public class DobViewModel
{
   [DateTypeWithPhrase()]
   public DateTime? DateOfBirth { get; set; }    
}

public class DataTypeWithPhraseAttributeAdapter : DataAnnotationsModelValidator<DateTypeWithPhraseAttribute>
{
   private readonly DateTypeWithPhraseAttribute _attribute;

   public DataTypeWithPhraseAttributeAdapter(ModelMetadata metadata, ControllerContext context, DateTypeWithPhraseAttribute attribute)
          : base(metadata, context, attribute)
   {
        _attribute = attribute;
   }

    public static void SelfRegister()
    {
         DataAnnotationsModelValidatorProvider
              .RegisterAdapter(
                  typeof(DateTypeWithPhraseAttribute),
                  typeof(DataTypeWithPhraseAttributeAdapter));
    }

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
    {
        return new[] { new ModelClientValidationDateRule(_attribute.ErrorMessage) };
    }
}

public class DateTypeWithPhraseAttribute : DataTypeAttribute
{
    public DateTypeWithPhraseAttribute() : base(DataType.Date)
    {
         ErrorMessageResourceName = null;
         ErrorMessage = ErrorPhrase;
    }

    public string ErrorPhrase = "Invalid Date";
 }
anouar.bagari
  • 2,084
  • 19
  • 30
webdevduck
  • 563
  • 5
  • 18

1 Answers1

0

It appears the error was being triggered when binding on postback. If the date was invalid, it would recognise there was an error, and would set the value of DateOfBirth to null, which would pass the custom validation. However, it had already failed, hence the default message being returned.

The solution I implemented was to change DateOfBirth to be a string, this would then bind correctly. I then overrode the IsValid method to validate if the string was in fact a valid date.

public class DobViewModel
{
   [DateTypeWithPhrase()]
   public string DateOfBirth { get; set; }    
}

public class DateTypeWithPhraseAttribute : DataTypeAttribute
{
    public DateTypeWithPhraseAttribute() : base(DataType.Date)
    {
         ErrorMessageResourceName = null;
         ErrorMessage = ErrorPhrase;
    }

    public string ErrorPhrase = "Invalid Date";

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        DateTime myDate;
        if (value == null || DateTime.TryParse(value.ToString(), out myDate))
        {
            return ValidationResult.Success;
        }
        return new ValidationResult(ErrorMessage);
    }
 }

A colleague of mine has since found a link to an article that raises the possibility of creating a custom model binder, which I will look into at a future date. The article is here and was originally found here.

Community
  • 1
  • 1
webdevduck
  • 563
  • 5
  • 18