Contents tagged with Validation

  • NHibernate Fluent Validation

    Some time ago, I wrote a post on fluent validation for Entity Framework Code First. I think it is a cool concept, and I decided to bring it into NHibernate!

    In a nutshell, what I want to be able to achieve is something like this:

       1: var validation = sessionFactory
       2:     .FluentlyValidate()
       3:     .Entity<SomeEntity>(x => x.SomeValue != "", "SomeValue is empty")
       4:     .Entity<AnotherEntity>(x => x.AnotherValue != 0, "AnotherValue is 0");

    You can see that whenever I am about to save (update or insert) some entity of types SomeEntity or AnotherEntity, the fluent validation will occur, and an exception will be thrown if the entity does not pass. Fluent validation consists of one lambda expression – which can have several conditions – applied to an entity and returning a boolean result.

    For this, I am using NHibernate’s listeners, and I am adding them dynamically through the ISessionFactory, this way it will apply to all ISessions spawned from it.

    Without further delay, here is the code, first, the session factory extensions:

       1: public static class SessionFactoryExtensions
       2: {
       3:     internal static readonly IDictionary<GCHandle, FluentValidation> validations = new ConcurrentDictionary<GCHandle, FluentValidation>();
       4:  
       5:     public static FluentValidation FluentlyValidate(this ISessionFactory sessionFactory)
       6:     {
       7:         var validation = GetValidator(sessionFactory);
       8:  
       9:         if (validation == null)
      10:         {
      11:             validation = Register(sessionFactory);
      12:         }
      13:  
      14:         return (validation);
      15:     }
      16:  
      17:     public static void DisableFluentValidation(this ISessionFactory sessionFactory)
      18:     {
      19:         Unregister(sessionFactory);
      20:     }
      21:  
      22:     internal static FluentValidation GetValidator(this ISessionFactory sessionFactory)
      23:     {
      24:         return (validations.Where(x => x.Key.Target == sessionFactory).Select(x => x.Value).SingleOrDefault());
      25:     }
      26:  
      27:     private static void Unregister(ISessionFactory sessionFactory)
      28:     {
      29:         var validation = validations.Where(x => x.Key.Target == sessionFactory).SingleOrDefault();
      30:  
      31:         if (Object.Equals(validation, null) == true)
      32:         {
      33:             validations.Remove(validation);
      34:         }
      35:  
      36:         (sessionFactory as SessionFactoryImpl).EventListeners.FlushEntityEventListeners = (sessionFactory as SessionFactoryImpl).EventListeners.FlushEntityEventListeners.Where(x => !(x is FlushEntityValidatorListener)).ToArray();
      37:     }
      38:  
      39:     private static FluentValidation Register(ISessionFactory sessionFactory)
      40:     {
      41:         var validation = (validations[GCHandle.Alloc(sessionFactory)] = new FluentValidation());
      42:         (sessionFactory as SessionFactoryImpl).EventListeners.FlushEntityEventListeners = (sessionFactory as SessionFactoryImpl).EventListeners.FlushEntityEventListeners.Concat(new IFlushEntityEventListener[] { new FlushEntityValidatorListener() }).ToArray();
      43:         return (validation);
      44:     }
      45: }

    This supports having multiple session factories, and because I am using a GCHandle to wrap them, they are not prevented from being garbage collected.

    Next, the class that does the actual validation:

       1: public sealed class FluentValidation
       2: {
       3:     private readonly IDictionary<Type, Dictionary<Delegate, String>> conditions = new ConcurrentDictionary<Type, Dictionary<Delegate, String>>();
       4:     
       5:     public FluentValidation Clear<T>()
       6:     {
       7:         foreach (var type in this.conditions.Where(x => typeof(T).IsAssignableFrom(x.Key)).Select(x => x.Key))
       8:         {
       9:             this.conditions.Remove(type);
      10:         }
      11:         
      12:         return (this);
      13:     }
      14:  
      15:     public FluentValidation Entity<T>(Func<T, Boolean> condition, String message)
      16:     {
      17:         if (this.conditions.ContainsKey(typeof(T)) == false)
      18:         {
      19:             this.conditions[typeof(T)] = new Dictionary<Delegate, String>();
      20:         }
      21:  
      22:         this.conditions[typeof(T)][condition] = message;            
      23:  
      24:         return (this);
      25:     }
      26:  
      27:     public void Validate(Object entity)
      28:     {
      29:         var applicableConditions = this.conditions.Where(x => entity.GetType().IsAssignableFrom(x.Key)).Select(x => x.Value);
      30:  
      31:         foreach (var applicableCondition in applicableConditions)
      32:         {
      33:             foreach (var condition in applicableCondition)
      34:             {
      35:                 var del = condition.Key;
      36:  
      37:                 if (Object.Equals(del.DynamicInvoke(entity), false) == true)
      38:                 {
      39:                     throw (new ValidationException(entity, condition.Value));
      40:                 }
      41:             }
      42:         }
      43:     }
      44: }

    This class holds a collection of validations for an entity type. If the validation fails, it throws an instance of a custom exception class:

       1: [Serializable]
       2: public sealed class ValidationException : Exception
       3: {
       4:     public ValidationException(Object entity, String message) : base(message)
       5:     {
       6:         this.Entity = entity;
       7:     }
       8:  
       9:     public Object Entity
      10:     {
      11:         get;
      12:         private set;
      13:     }        
      14: }

    Finally, the NHibernate listener:

       1: sealed class FlushEntityValidatorListener : IFlushEntityEventListener
       2: {
       3:     #region IFlushEntityEventListener Members
       4:  
       5:     public void OnFlushEntity(FlushEntityEvent @event)
       6:     {
       7:         var validator = @event.Session.SessionFactory.GetValidator();
       8:  
       9:         if (validator != null)
      10:         {
      11:             validator.Validate(@event.Entity);
      12:         }
      13:     }
      14:  
      15:     #endregion
      16: }

    When we no longer need fluent validation, we can disable it altogether:

       1: sessionFactory.DisableFluentValidation();

    Or just for a particular entity:

       1: validation.Clear<SomeEntity>();

    As always, hope you like it! Do send me your comments!

    Read more...

  • Entity Framework Pitfalls: Validation Does Not Load Lazy Properties

    In a nutshell: Entity Framework Code First (EFCF) validation does not load lazy properties. If any of these properties is marked as required, and it is not loaded, a validation error will occur.

    While I understand the reason – imagine you are saving lots of entities where a required property is not loaded, this will cause lots of accesses to the database just for checking that the required entity exists – I think the way things are is not very productive. I hope the Entity Framework team can come up with a solution, I’ll probably propose something myself.

    Imagine you have a class model such as:

       1: public class Parent
       2: {
       3:     public Int32 ParentId { get; set; }
       4:     public virtual ICollection<Child> Children { get; set; }
       5: }
       6:  
       7: public class Child
       8: {
       9:     public Int32 ChildId { get; set; }
      10:     [Required]
      11:     public virtual Parent Parent { get; set; }
      12: }

    Say you load a child and make some change:

       1: Child c = ctx.Children.Find(1);
       2: c.SomeProperty = "...";
       3:  
       4: ctx.SaveChanges();

    This will throw a DbEntityValidationException, because EFCF will think that the Child instance does not have its Parent property set. This is really annoying and is the source of great frustration.

    Of course, there are some workarounds:

    • Explicitly force loading all lazy loaded properties before calling SaveChanges;
       1: var p = c.Parent;
    • Include all lazy loaded properties in the query (best option), such as:
       1: var c = ctx.Children.Where(x => x.ChildId == 1).Include(x => x.Parent).Single();
    • Disable validation at all (not recommended):
       1: ctx.Configuration.ValidateOnSaveEnabled = false;
    • Disable lazy loading globally (also not recommended):
       1: ctx.Configuration.LazyLoadingEnabled = false;
       2: ctx.Configuration.ProxyCreationEnabled = false;
    • Finally, you can remove the required constraint (not good as well):
       1: public virtual Parent Parent { get; set; }

    Read more...

  • Entity Framework Code First Fluent Validation

    Back to Entity Framework Code First (EFCF) validation. On my previous post I mentioned that EFCF did not support fluent validation. While this is true, it isn’t too hard to implement one such mechanism, which is exactly why I am writing this! Smile

    I will be using the SavingChanges event to inject the validation logic, which will be implemented by strongly typed delegates. Let’s see some code:

       1: public static class DbContextExtensions
       2: {
       3:     private static IDictionary<Type, Tuple<Delegate, String>> entityValidations = new ConcurrentDictionary<Type, Tuple<Delegate, String>>();
       4:  
       5:     public static void AddEntityValidation<TEntity>(this DbContext context, Func<TEntity, Boolean> validation, String message) where TEntity : class
       6:     {
       7:         if (context == null)
       8:         {
       9:             throw new ArgumentNullException("context");
      10:         }
      11:  
      12:         if (validation == null)
      13:         {
      14:             throw new ArgumentNullException("validation");
      15:         }
      16:  
      17:         if (String.IsNullOrWhiteSpace(message) == true)
      18:         {
      19:             throw new ArgumentNullException("message");
      20:         }
      21:  
      22:         if (entityValidations.ContainsKey(typeof(TEntity)) == false)
      23:         {
      24:             (context as IObjectContextAdapter).ObjectContext.SavingChanges += delegate
      25:             {
      26:                 if (context.Configuration.ValidateOnSaveEnabled == true)
      27:                 {
      28:                     IEnumerable<TEntity> entities = context.ChangeTracker.Entries<TEntity>().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified).Select(x => x.Entity).ToList();
      29:  
      30:                     foreach (TEntity entity in entities)
      31:                     {
      32:                         String error = ValidateEntity(entity);
      33:  
      34:                         if (String.IsNullOrWhiteSpace(error) == false)
      35:                         {
      36:                             throw (new ValidationException(error));
      37:                         }
      38:                     }
      39:                 }
      40:             };
      41:         }
      42:  
      43:         entityValidations[typeof(TEntity)] = new Tuple<Delegate, String>(validation, message);
      44:     }
      45:  
      46:     private static String ValidateEntity<TEntity>(TEntity entity)
      47:     {
      48:         Type entityType = typeof(TEntity);
      49:  
      50:         if (entityValidations.ContainsKey(entityType) == true)
      51:         {
      52:             Tuple<Delegate, String> entry = entityValidations[entityType];
      53:             Func<TEntity, Boolean> validation = entry.Item1 as Func<TEntity, Boolean>;
      54:  
      55:             if (validation(entity) == false)
      56:             {
      57:                 return (entry.Item2);
      58:             }
      59:         }
      60:  
      61:         return (null);
      62:     }
      63: }

    We have an extension method that allows declaring, for an entity type, a validation expression, such as this:

       1: ctx.AddEntityValidation<SomeEntity>(x => x.SomeProperty != null, "SomeProperty is required");

    The validation will be fired when the SaveChanges method is called and the errors will be encapsulated in a ValidationException:

       1: try
       2: {
       3:     ctx.SaveChanges();
       4: }
       5: catch (ValidationException ex)
       6: {
       7:     //see content of ex.ValidationResult.ErrorMessage
       8: }

    This code can certainly be improved – multiple validations per entity, property-based validations, etc – but I think it is good enough to illustrate my technique.

    One final note: the fluent validation will only be fired if the ValidateOnSaveEnabled property is set to true, which is the default.

    Read more...

  • Entity Framework Code First Validation

    Introduction

    Most persistence frameworks implement some kind of custom validation of entities before they are sent to the database. By custom I mean something more than just “is not null”, “has XX characters”, etc. This typically includes individual properties as well as validation of the entity as a whole – for example, checking that a property’s value is valid when used together with another property’s value.

    Entity Framework Code First is no exception. Out of the box it already offers a number of possibilities for validating entities that cover typical scenarios: validation by attributes or by a validation method. One validation left out is one based on XML, but since Code First doesn’t really use XML, it should be no surprise, and the other is fluent validation, something that really should be supported.

    Let’s explore each of these possibilities.

    Overriding ValidateEntity

    The DbContext class has a virtual method called ShouldValidateEntity that is called for each entity about to be persisted – meaning, inserted or updated –, and, when it returns true – which it does by default – will trigger a call to ValidateEntity, another virtual method. In this method, we have a chance to validate our entities any way we like. An example might be, for instance, checking if the entity to be saved implements IDataErrorInfo and extract validation information from this implementation:

       1: protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<Object, Object> items)
       2: {
       3:     DbEntityValidationResult result = base.ValidateEntity(entityEntry, items);
       4:     IDataErrorInfo dei = entityEntry.Entity as IDataErrorInfo;
       5:     
       6:     foreach (String propertyName in entityEntry.CurrentValues.PropertyNames)
       7:     {
       8:         String errorMessage = dei[propertyName];
       9:  
      10:         if (String.IsNullOrWhiteSpace(errorMessage) == false)
      11:         {
      12:             result.ValidationErrors.Add(new DbValidationError(propertyName, errorMessage));
      13:         }
      14:     }
      15:  
      16:     return (result);
      17: }

    For the validation to occur, the ValidateOnSave property must be true, which it is by default.
    Don’t forget to always call the base implementation!

    Applying Validation Attributes

    Another option, which also applies to ASP.NET MVC validation (see http://weblogs.asp.net/ricardoperes/archive/2012/06/03/asp-net-mvc-validation-complete.aspx) is using validation attributes, that is, attributes that inherit from ValidationAttribute. The base ValidateEntity method of DbContext also checks for these attributes, another reason why you should always call it. Let’s see an example:

       1: [Serializable]
       2: [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
       3: public sealed class PositiveAttribute : ValidationAttribute
       4: {
       5:     protected override ValidationResult IsValid(Object value, ValidationContext validationContext)
       6:     {
       7:         Int64 longValue = Convert.ToInt64(value);
       8:  
       9:         if (longValue <= 0)
      10:         {
      11:             return (new ValidationResult("Value cannot be negative or zero"));
      12:         }
      13:  
      14:         return (ValidationResult.Success);
      15:     }
      16: }

    You would then apply this to some property in your entity:

       1: public class MyEntity
       2: {
       3:     [Positive]
       4:     public Int64 MyAlwaysPositiveNumber { get; set; }
       5: }

    The “problem” with this approach is that you must include any assemblies containing these custom validation attributes together with your model. If they are on the same assembly, there’s no problem.

    By the way, you can specify multiple validation attributes and you can even apply them to the whole class, not just a property.

    Implementing IValidatableObject

    Another option, also common to MVC, is having your entities implement IValidatableObject. This interface defines a contract for returning a collection of validation errors for an entity. Here’s a sample implementation:

       1: public class Contract : IValidatableObject
       2: {
       3:     public String Name { get; set; }
       4:     public DateTime StartDate { get; set; }
       5:     public DateTime EndDate { get; set; }
       6:  
       7:     public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
       8:     {
       9:         if (this.StartDate >= this.EndDate)
      10:         {
      11:             yield return (new ValidationResult("The end date is before or the same as the start date", new String[] { "StartDate", "EndDate" }));
      12:         }
      13:     }
      14: }

    Handling SavingChanges Event

    The “underlying” ObjectContext – which, in fact, is only created if requested – exposes a SavingChanges event which is triggered whenever Entity Framework is about to send changes to the database, typically whenever the SaveChanges method is called. If we handle this event, we can perform our custom validation before our entities are saved, and in case something is wrong we can throw an exception to cancel the saving process:

       1: (ctx as IObjectContextAdapter).ObjectContext.SavingChanges += ObjectContext_SavingChanges;
       2:  
       3: void ObjectContext_SavingChanges(Object sender, EventArgs e)
       4: {
       5:     ObjectContext octx = sender as ObjectContext;
       6:     IEnumerable<Object> entities = octx.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified).Select(x => x.Entity);
       7:  
       8:     //do custom validation and throw an exception if something wrong is found
       9:  
      10: }

    This has the arguable advantage that it decouples the validation process from the entities and the context themselves.

    Conclusion

    In case you are using any of these validation techniques, always surround calls to SaveChanges inside a try…catch block and look out for a DbEntityValidationException or your own exception, if you followed the SavingChanges approach. Inside DbEntityValidationException you have an EntityValidationErrors that contains all the details:

       1: try
       2: {
       3:     ctx.SaveChanges();
       4: }
       5: catch (DbEntityValidationException ex)
       6: {
       7:     foreach (DbEntityValidationResult result in ex.EntityValidationErrors)
       8:     {
       9:         //..
      10:     }
      11: }

    Alternatively, you can explicitly call GetValidationErrors and see the collection of errors from all sources, except, of course, SavingChanges, because the context is not actually in the process of saving changes, for all entities currently being tracked by the context.

    The order by which these validation processes are applied is:

    1. ValidateEntity
    2. ValidationAttribute (from base ValidateEntity)
    3. IValidatableObject (from base ValidateEntity
    4. SavingChanges (only if no errors are found)

    Pick the one that better suits your needs!

    Read more...

  • My All Time Favorite Posts

    Since this blog started, back in 2008, I wrote a lot of posts. I’d say some are still up to date. I picked a few of them, those I’m more proud of, in no particular order.

    ASP.NET Web Forms:

    ASP.NET MVC:

    NHibernate:

    .NET:

    Let me know what you think of them! Are there others you particularly enjoyed?

    Read more...

  • ASP.NET MVC Validation Complete

    OK, so let’s talk about validation. Most people are probably familiar with the out of the box validation attributes that MVC knows about, from the System.ComponentModel.DataAnnotations namespace, such as EnumDataTypeAttribute, RequiredAttribute, StringLengthAttribute, RangeAttribute, RegularExpressionAttribute and CompareAttribute from the System.Web.Mvc namespace. All of these validators inherit from ValidationAttribute and perform server as well as client-side validation. In order to use them, you must include the JavaScript files MicrosoftMvcValidation.js, jquery.validate.js or jquery.validate.unobtrusive.js, depending on whether you want to use Microsoft’s own library or jQuery. No significant difference exists, but jQuery is more extensible.

    Read more...

  • Data Annotations Property Validator for ASP.NET

    Entity Framework, LINQ to SQL and ASP.NET MVC support Microsoft's new validation API, which you can find on System.ComponentModel.DataAnnotations. It basically consists on attribute classes, inherited from System.ComponentModel.DataAnnotations.ValidationAttribute. It is very easy to define your own, although Enterprise Library, xVal and Spring.NET validations are considerably power powerfull.

    I wanted to have a custom ASP.NET validator that would validate the value of a form control against the validation attributes defined for a given property of a class, in a way similar to the Web Client Software Factory's PropertyProxyValidator, like you can read in this post. This is what I came up with: class DataAnnotationsValidator!

    Here is the code:

    public class DataAnnotationsValidator : BaseValidator

    {

        protected override void OnInit(EventArgs e)

        {

            if ((this.Enabled == true) && (this.Visible == true))

            {

                this.Page.RegisterRequiresControlState(this);

            }

            base.OnInit(e);

        }

        protected override void LoadControlState(Object savedState)

        {

            Object [] state = savedState as Object [];

            base.LoadControlState(state [ 0 ]);

            this.DisplayMode = (ValidationSummaryDisplayMode) state [ 1 ];

            this.PropertyName = (String) state [ 2 ];

            this.SourceTypeName = (String) state [ 3 ];

        }

        protected override Object SaveControlState()

        {

            Object [] state = new Object [ 4 ];

            state [ 0 ] = base.SaveControlState();

            state [ 1 ] = this.DisplayMode;

            state [ 2 ] = this.PropertyName;

            state [ 3 ] = this.SourceTypeName;

            return (state);

        }

        protected override Boolean EvaluateIsValid()

        {

            if ((String.IsNullOrEmpty(this.SourceTypeName) == true) || (String.IsNullOrEmpty(this.PropertyName) == true))

            {

                return (true);

            }

            Type type = Type.GetType(this.SourceTypeName, false);

            if (type != null)

            {

                PropertyInfo prop = type.GetProperty(this.PropertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);

                if (prop != null)

                {

                    ValidationAttribute [] attrs = prop.GetCustomAttributes(typeof(ValidationAttribute), true) as ValidationAttribute [];

                    List<ValidationException> errors = new List<ValidationException>();

                    String value = this.GetControlValidationValue(this.ControlToValidate);

                    if (attrs.Length == 0)

                    {

                        MetadataTypeAttribute [] metadata = type.GetCustomAttributes(typeof(MetadataTypeAttribute), true) as MetadataTypeAttribute [];

     

                        if (metadata.Length != 0)

                        {

                            prop = metadata[0].MetadataClassType.GetProperty(this.PropertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);

                            if (prop != null)

                            {

                                attrs = prop.GetCustomAttributes(typeof(ValidationAttribute), true) as ValidationAttribute [];

                            }

                        }

                    }

                    for (Int32 i = 0; i < attrs.Length; ++i)

                    {

                        try

                        {

                            attrs [ i ].Validate(value, prop.Name);

                        }

                        catch (ValidationException ve)

                        {

                            errors.Add(ve);

                        }

                        catch

                        {

                        }

                    }

                    this.ErrorMessage = this.formatErrorMessage(errors);

                    return (errors.Count == 0);

                }

            }

            this.ErrorMessage = String.Empty;

            return (true);

        }

        private String formatErrorMessage(IList<ValidationException> results)

        {

            String str = String.Empty;

            String str2 = String.Empty;

            String str3 = String.Empty;

            String str4 = String.Empty;

            StringBuilder builder = new StringBuilder();

            switch (this.DisplayMode)

            {

                case ValidationSummaryDisplayMode.List:

                    str3 = "<br/>";

                    break;

                case ValidationSummaryDisplayMode.SingleParagraph:

                    str3 = " ";

                    str4 = "<br/>";

                    break;

                default:

                    str = "<ul>";

                    str2 = "<li>";

                    str3 = "</li>";

                    str4 = "</ul>";

                    break;

            }

            if (results.Count != 0)

            {

               builder.Append(str);

                foreach (ValidationException result in results)

                {

                    builder.Append(str2);

                    builder.Append(result.Message);

                    builder.Append(str3);

                }

                builder.Append(str4);

            }

            return (builder.ToString());

        }

        [Browsable(true)]

        [DefaultValue(ValidationSummaryDisplayMode.List)]

        public ValidationSummaryDisplayMode DisplayMode

        {

            get;

            set;

        }

        [Browsable(true)]

        [DefaultValue("")]

        public String PropertyName

        {

            get;

            set;

        }

        [Browsable(true)]

        [DefaultValue("")]

        public String SourceTypeName

        {

            get;

            set;

        }

    }

    As you can see, it is smart enough to try to find the validation attributes on a metadata class defined with a MetadataTypeAttribute attribute, like you would use with generated code, such as Entity Framework's. It also supports all of ValidationSummaryDisplayMode's options.

    This is how you would use it:

     

    <asp:TextBox runat="server" ID="text" />

    <blog:DataAnnotationsValidator runat="server" ControlToValidate="text" SourceTypeName="SomeClass, SomeAssembly" PropertyName="SomeProperty" />

    <asp:Button runat="server" Text="Validate" OnClick="OnValidate" />

    Suppose the class you want to validate looks like this:

    public class SomeClass

        [Required]

        [RegularExpression(@"\d\d\d")]

        public String SomeProperty

        {

            get;

            set;

        }

    }

    And that's it! Happy validation!

    Bookmark and Share

    Read more...