locked
EF Code First and custom Validation Attributes RRS feed

  • Question

  • Hi there,

    I am building a project that uses EF Code First CTP 5 with POCO classes and MVC3. I would like to create custom attributes for validation so validation takes place at the MVC and at the EF level. Here's a quick demo attribute to show you what I mean:

      public class GreaterThanAttributeValidationAttribute
      {
        public string OtherPropertyName { getprivate set; }

        public GreaterThanAttribute(string otherPropertyName)
        {
          OtherPropertyName = otherPropertyName;
          
        }

        protected override ValidationResult IsValid(object value, 
                ValidationContext validationContext)
        {
          var otherPropertyInfo = validationContext.ObjectType.GetProperty(
                        OtherPropertyName);
          var otherDate = (DateTime)otherPropertyInfo.GetValue(
                        validationContext.ObjectInstance, null);
          var thisDate = (DateTime)value;

          if (thisDate <= otherDate)
          {
            return new ValidationResult("Incorrect date.");
          }
          return null;
        }
      }

    This attribute compares the value of one date property with another (identified by OtherPropertyName).

    This works well in MVC. When this code is called, the ObjectInstance is my own POCO class, such as an Order, a Customer and so on. This means that the value of a property such as an OrderDate can be retrieved correctly.

    When MVC validation has passed, EF executes this code again. However, at this stage, validationContext.ObjectInstance is not my POCO type, but an Entity Type.

    What do I need to do in order to see properties defined on my POCO class when EF calls IsValid? I debugged the ObjectInstance and tried various casting options, but I could never get at my POCO type.

    Any ideas?

    Thanks in advance,

    Imar

    Thursday, January 20, 2011 10:10 PM

Answers

  • Hi Imar,

    This is a bug in our validation, the ObjectInstance should contain your POCO instance (the same as when running in MVC).

    Unfortunately there isn't a good way for you to get the object instance because the object we are setting to ObjectInstance is an internal type. It's very hacky but you could use reflection to access the Entity property on this type.

    ~Rowan

    Friday, January 21, 2011 10:18 PM
    Moderator

All replies

  • Hi Imar,

    This is a bug in our validation, the ObjectInstance should contain your POCO instance (the same as when running in MVC).

    Unfortunately there isn't a good way for you to get the object instance because the object we are setting to ObjectInstance is an internal type. It's very hacky but you could use reflection to access the Entity property on this type.

    ~Rowan

    Friday, January 21, 2011 10:18 PM
    Moderator
  • Hi Rowan,

    Aha, thanks, that explains it. Is a fix for this planned for RTM?

    And yes, I found the Entity property of the internal type. I just stopped there, as using reflection to find an (interna) EF type sort of defeats the purpose of using POCO classes.... ;-)

    Thanks,

    Imar

    Friday, January 21, 2011 11:48 PM
  • Hi Imar,

    Yes, this will be fixed for RTM.

    ~Rowan

    Tuesday, January 25, 2011 7:10 PM
    Moderator
  • i'm having the same problem. unfortunately i searched for this and finding out that it is beeing a bug for half a day now :(

    maybe you can post this on the ado.net teams blog.

     

    btw mvc compareattribute isn't working too because of this bug.

     

    i tried to fix my code by asking for the type, but because System.Data.Entity.Internal.InternalEntityEntry is an internal class this code won't work:

    if
    

     (validationContext.ObjectType.Equals(typeof

    (System.Data.Entity.Internal.InternalEntityEntry)))


    {


    return

     null

    ;


    }





    how to fix it? when will be the next CTP or RTM comming out that fixes this bug?

    edit2:
    if (validationContext.ObjectType.FullName == "System.Data.Entity.Internal.InternalEntityEntry" ) is working!!!

    • Edited by toebens2 Monday, February 21, 2011 11:59 AM cant fix my code because of internal type
    Monday, February 21, 2011 11:49 AM
  • Hi,

    Yes, this will be fixed in our upcoming go-live release later this quarter (Q1 2011).

    ~Rowan

    Wednesday, February 23, 2011 10:32 PM
    Moderator