Question

I have a ValidationAttribute that I have created which is shared between the Server, and Client. In order to get the validation attribute to properly generate to the client when referenced within a data helper class I had to be very specific in how I built it.

The problem I'm having is that for some reason when I return a ValidationResult from my custom validation attribute class it is not handled the same as other validation attributes on the client UI. Instead of displaying the error it does nothing. It will properly validate the object though, it just doesn't display the failed validation result.

Below is the code for one of my custom validation classes.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;

namespace Project.Web.DataLayer.ValidationAttributes
{
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
    public class DisallowedChars : ValidationAttribute
    {
        public string DisallowedCharacters
        {
            get
            {
                return new string(this.disallowedCharacters);
            }

            set
            {
                this.disallowedCharacters = (!this.CaseSensitive ?     value.ToLower().ToCharArray() : value.ToCharArray());
            }
        }

        private char[] disallowedCharacters = null;

        private bool caseSensitive;

        public bool CaseSensitive
        {
            get
            {
                return this.caseSensitive;
            }

            set
            {
                this.caseSensitive = value;
            }
        }

        protected override ValidationResult IsValid(object value, ValidationContext    validationContext)
        {
            if (value != null && this.disallowedCharacters.Count() > 0)
            {
                string Value = value.ToString();

                foreach(char val in this.disallowedCharacters)
                {
                    if ((!this.CaseSensitive && Value.ToLower().Contains(val)) ||     Value.Contains(val))
                    {
                        return new ValidationResult(string.Format(this.ErrorMessage != null ? this.ErrorMessage : "'{0}' is not allowed an allowed character.", val.ToString()));
                    }
                }
            }

            return ValidationResult.Success;
        }
    }
}

This is how I use it above my Properties on both the server, and client.

[DisallowedChars(DisallowedCharacters = "=")]

And I've tried several different ways of setting up the binding.

{Binding Value, NotifyOnValidationError=True}

As well as

{Binding Value, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True, ValidatesOnNotifyDataErrors=True}

None of these seem to make the forms that they are bound too validate the entries. I've tried using this attribute on values that are bound to TextBoxes, XamGrids, and neither of those properly validate like they should.

This problem only seems to be when I am attempting to use the ValidationResult on the server side. If I use the validation result on a value in my view model then it will properly validate. I need to find a way to make this properly validate from the generated code though.

Any thoughts would be very much appreciated.

Was it helpful?

Solution

You need to specify the MemberNames that are associated with the ValidationResult. The constructor of ValidationResult has an additional parameter to specify the properties that are associated with the result. If you do not specify any properties, the result is handled as a validation error on entity level.

So in your case, it should be fixed, when you pass in the name of the property to the constructor of the ValidationResult.

protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
 if (value != null && this.disallowedCharacters.Count() > 0) {
   string Value = value.ToString();

   foreach(char val in this.disallowedCharacters) {
     if ((!this.CaseSensitive && Value.ToLower().Contains(val)) || Value.Contains(val)) {
       //return new ValidationResult(string.Format(this.ErrorMessage != null ? this.ErrorMessage : "'{0}' is not allowed an allowed character.", val.ToString()));
       string errorMessage = string.Format(this.ErrorMessage != null ? this.ErrorMessage : "'{0}' is not allowed an allowed character.", val.ToString());
       return new ValidationResult(errorMessage, new string[] { validationContext.MemberName});
     }
   }
 }

 return ValidationResult.Success;
}

For the bindings you don´t need to specify anything else. So the simple Binding

{Binding Value}

should display errors, cause ValidatesOnNotifyDataErrors is set to true implicitly. NotifyOnValidationError populates ValidationErrors to other elements like ValidationSummary.

Jeff Handly has a really goog blog post about Validation in WCF Ria Services and Silverlight, i can recommened to read.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top