0

I have a problem attaching metadata class to ADO.NET entity data model generated classes. According to the following links...

http://blogs.microsoft.co.il/blogs/gilf/archive/2011/01/20/adding-metadata-to-entities-in-the-data-model.aspx

http://msdn.microsoft.com/en-us/library/cc679243.aspx

http://goneale.com/2009/03/04/using-metadatatype-attribute-with-aspnet-mvc-xval-validation-framework/

http://davidhayden.com/blog/dave/archive/2008/01/06/ASPNETDynamicDataTutorialBuddyMetadataProviderCustomMetadataProviders.aspx

http://davidhayden.com/blog/dave/archive/2008/05/15/DynamicDataWebsitesScaffoldTableScaffoldColumnAttributes.aspx

I created a metadata class to add some Attributes to properties. I could add this attributes to properties in generated classes and It works but I wanted to avoid loosing this attributes every time I have to update and recreate my ADO.NET entity data model.

My question is, what am I doing wrong ? Why in runtime properties does not have my custom attributes ?

This is a part of generated data class

[EdmEntityTypeAttribute(NamespaceName="HelpMeHowModel", Name="Article")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
[MetadataType(typeof(ArticleMetaData))]
public partial class Article : EntityObject
{
    #region Primitive Properties

    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
    [DataMemberAttribute()]
    public global::System.Boolean IsPublished
    {
        get
        {
            return _IsPublished;
        }
        set
        {
            OnIsPublishedChanging(value);
            ReportPropertyChanging("IsPublished");
            _IsPublished = StructuralObject.SetValidValue(value);
            ReportPropertyChanged("IsPublished");
            OnIsPublishedChanged();
        }
    }
    private global::System.Boolean _IsPublished;
    partial void OnIsPublishedChanging(global::System.Boolean value);
    partial void OnIsPublishedChanged();

...

.. and this is my metadata class

public class ArticleMetaData
{
    #region Primitive Properties

    [BoolFunction(BoolFunction.ThreeStateRadioButton)]
    public global::System.Boolean IsPublished { get; set; }
2
  • I forgot to say that I am developing an regular ASP.NET application ! Commented Oct 23, 2011 at 19:34
  • check this this out , i already answered this question here stackoverflow.com/a/24757520/3050647 Commented Jul 15, 2014 at 12:18

1 Answer 1

2

For everybody looking for the solution for the same problem...

Adding custom attributes to partial MetadataType class is possible and it works but there is a little problem.

Using

PropertyInfo pi;

pi.GetCustomAttributes(...) 

will get the Attributes from the main class only and not from the class used as MetadataType.

Based on solution explained here

Attribute.IsDefined doesn't see attributes applied with MetadataType class

I created two extension methods for PropertyInfo class to get all attributes.

namespace FAIN.Framework.Commons
{
    public static class PropertyInfoEx
    {
        public static object[] GetAllCustomAttributes(this PropertyInfo pi, bool inherit)
        {
            return GetAllCustomAttributes(pi, null, inherit);
        }
        /// <summary>
        /// Get Custom Attributes + attributes added in MetadataType
        /// </summary>
        /// <param name="pi"></param>
        /// <param name="attributeType"></param>
        /// <param name="inherit"></param>
        /// <returns></returns>
        public static object[] GetAllCustomAttributes(this PropertyInfo pi, Type attributeType, bool inherit)
        {
            if (pi == null) return null;
            List<object> allAttributes = new List<object>();
            object[] attributes = null;
            if (attributeType != null)
            {
                attributes = pi.GetCustomAttributes(attributeType, inherit);
            }
            else
            {
                attributes = pi.GetCustomAttributes(inherit);
            }
            allAttributes.AddRange(attributes);

            // search all the Metadata of the class declaring the property to get all CustomAttributes if there are any
            MetadataTypeAttribute[] metadataTypes = pi.DeclaringType.GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType<MetadataTypeAttribute>().ToArray();
            foreach (MetadataTypeAttribute metadata in metadataTypes)
            {

                if (metadata != null)
                {
                    PropertyInfo[] properties = metadata.MetadataClassType.GetProperties();
                    PropertyInfo propertyInfo = properties.Where(p => p.Name == pi.Name).FirstOrDefault();
                    if (propertyInfo != null)
                    {
                        if (attributeType != null)
                        {
                            attributes = propertyInfo.GetCustomAttributes(attributeType, inherit);
                        }
                        else
                        {
                            attributes = propertyInfo.GetCustomAttributes(inherit);
                        }
                        allAttributes.AddRange(attributes);
                    }
                }
            }

            return allAttributes.ToArray();
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.