Example #1
0
        /// <summary>
        /// Gets the entity fields for a specific Entity
        /// </summary>
        /// <param name="entityType">Type of the entity.</param>
        /// <param name="includeOnlyReportingFields">if set to <c>true</c> [include only reporting fields].</param>
        /// <param name="limitToFilterableFields">if set to <c>true</c> [limit to filterable fields].</param>
        /// <returns></returns>
        public static List <EntityField> GetEntityFields(Type entityType, bool includeOnlyReportingFields = true, bool limitToFilterableFields = true)
        {
            List <EntityField> entityFields = null;

            _workflowTypeNameLookup = null;

            if (HttpContext.Current != null)
            {
                entityFields = HttpContext.Current.Items[EntityHelper.GetCacheKey(entityType, includeOnlyReportingFields, limitToFilterableFields)] as List <EntityField>;
                if (entityFields != null)
                {
                    return(entityFields);
                }
            }

            if (entityFields == null)
            {
                entityFields = new List <EntityField>();
            }

            List <PropertyInfo> entityProperties = entityType.GetProperties().ToList();

            // filter the properties to narrow down the ones that we want to include in EntityFields
            var filteredEntityProperties = entityProperties
                                           .Where((p) =>
            {
                var includeForReportingAttribute = p.GetCustomAttribute <IncludeForReportingAttribute>() != null;

                // if the property has an IncludeForReportingAttribute, include it regardless
                if (includeForReportingAttribute)
                {
                    return(true);
                }

                bool hideFromReporting = false;
                if (includeOnlyReportingFields)
                {
                    hideFromReporting = p.GetCustomAttribute <HideFromReportingAttribute>() != null;
                }

                // if the property should be hidden from reporting, don't show it
                if (hideFromReporting)
                {
                    return(false);
                }

                bool isMappedDatabaseField = Reflection.IsMappedDatabaseProperty(p);
                if (!isMappedDatabaseField)
                {
                    return(false);
                }

                return(true);
            }).ToList();

            // Go thru filteredEntityProperties and create the list of EntityFields that we can include
            foreach (var property in filteredEntityProperties)
            {
                EntityField entityField = new EntityField(property.Name, FieldKind.Property, property);
                entityField.IsPreviewable = property.GetCustomAttributes(typeof(PreviewableAttribute), true).Any();
                var fieldTypeAttribute = property.GetCustomAttribute <Rock.Data.FieldTypeAttribute>();

                // check if we can set it from the fieldTypeAttribute
                if ((fieldTypeAttribute != null) && SetEntityFieldFromFieldTypeAttribute(entityField, fieldTypeAttribute))
                {
                    // intentionally blank, entity field is already setup
                }

                // Enum Properties
                else if (property.PropertyType.IsEnum)
                {
                    entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.SINGLE_SELECT.AsGuid());

                    var list = new List <string>();
                    foreach (var value in Enum.GetValues(property.PropertyType))
                    {
                        list.Add(string.Format("{0}^{1}", value, value.ToString().SplitCase()));
                    }

                    var listSource = string.Join(",", list);
                    entityField.FieldConfig.Add("values", new Field.ConfigurationValue(listSource));
                    entityField.FieldConfig.Add("fieldtype", new Field.ConfigurationValue("rb"));
                }

                // Boolean properties
                else if (property.PropertyType == typeof(bool) || property.PropertyType == typeof(bool?))
                {
                    entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.BOOLEAN.AsGuid());
                }

                // Datetime properties
                else if (property.PropertyType == typeof(DateTime) || property.PropertyType == typeof(DateTime? ))
                {
                    var colAttr = property.GetCustomAttributes(typeof(ColumnAttribute), true).FirstOrDefault();
                    if (colAttr != null && (( ColumnAttribute )colAttr).TypeName == "Date")
                    {
                        entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.DATE.AsGuid());
                    }
                    else
                    {
                        entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.DATE_TIME.AsGuid());
                    }
                }

                // Decimal properties
                else if (property.PropertyType == typeof(decimal) || property.PropertyType == typeof(decimal? ))
                {
                    entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.DECIMAL.AsGuid());
                }

                // Text Properties
                else if (property.PropertyType == typeof(string))
                {
                    entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.TEXT.AsGuid());
                }

                // Integer Properties (which may be a DefinedValue)
                else if (property.PropertyType == typeof(int) || property.PropertyType == typeof(int?))
                {
                    entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.INTEGER.AsGuid());

                    var definedValueAttribute = property.GetCustomAttribute <Rock.Data.DefinedValueAttribute>();
                    if (definedValueAttribute != null)
                    {
                        // Defined Value Properties
                        Guid?definedTypeGuid = definedValueAttribute.DefinedTypeGuid;
                        if (definedTypeGuid.HasValue)
                        {
                            var definedType = DefinedTypeCache.Get(definedTypeGuid.Value);
                            entityField.Title = definedType != null ? definedType.Name : property.Name.Replace("ValueId", string.Empty).SplitCase();
                            if (definedType != null)
                            {
                                entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.DEFINED_VALUE.AsGuid());
                                entityField.FieldConfig.Add("definedtype", new Field.ConfigurationValue(definedType.Id.ToString()));
                            }
                        }
                    }
                }

                if (entityField != null && entityField.FieldType != null)
                {
                    entityFields.Add(entityField);
                }
            }

            // Get Attributes
            var entityTypeCache = EntityTypeCache.Get(entityType, true);

            if (entityTypeCache != null)
            {
                int entityTypeId = entityTypeCache.Id;

                var entityAttributesCache = AttributeCache.GetByEntity(entityTypeCache.Id);

                List <AttributeCache> cacheAttributeList = entityAttributesCache.SelectMany(a => a.AttributeIds).Distinct().Select(a => AttributeCache.Get(a)).ToList();

                if (entityType == typeof(Group) || entityType == typeof(GroupMember))
                {
                    // in the case of Group or GroupMember, show attributes that are entity global, but also ones that are qualified by GroupTypeId
                    cacheAttributeList = cacheAttributeList
                                         .Where(a =>
                                                a.EntityTypeQualifierColumn == null ||
                                                a.EntityTypeQualifierColumn == string.Empty ||
                                                a.EntityTypeQualifierColumn == "GroupTypeId").ToList();
                }
                else if (entityType == typeof(ConnectionRequest))
                {
                    // in the case of Connection Requests, show attributes that are entity global, but also ones that are qualified by ConnectionOpportunityId
                    cacheAttributeList = cacheAttributeList
                                         .Where(a =>
                                                a.EntityTypeQualifierColumn == null ||
                                                a.EntityTypeQualifierColumn == string.Empty ||
                                                a.EntityTypeQualifierColumn == "ConnectionOpportunityId"
                                                ).ToList();
                }
                else if (entityType == typeof(Registration))
                {
                    // in the case of Registrations, show attributes that are entity global, but also ones that are qualified by RegistrationTemplateId
                    cacheAttributeList = cacheAttributeList
                                         .Where(a =>
                                                a.EntityTypeQualifierColumn == null ||
                                                a.EntityTypeQualifierColumn == string.Empty ||
                                                a.EntityTypeQualifierColumn == "RegistrationTemplateId"
                                                ).ToList();
                }
                else if (entityType == typeof(ContentChannelItem))
                {
                    // in the case of ContentChannelItem, show attributes that are entity global, but also ones that are qualified by ContentChannelTypeId or ContentChannelId
                    cacheAttributeList = cacheAttributeList
                                         .Where(a =>
                                                a.EntityTypeQualifierColumn == null ||
                                                a.EntityTypeQualifierColumn == string.Empty ||
                                                a.EntityTypeQualifierColumn == "ContentChannelTypeId" ||
                                                a.EntityTypeQualifierColumn == "ContentChannelId"
                                                ).ToList();
                }
                else if (entityType == typeof(Rock.Model.Workflow))
                {
                    // in the case of Workflow, show attributes that are entity global, but also ones that are qualified by WorkflowTypeId (and have a valid WorkflowTypeId)
                    var validWorkflowTypeIds = WorkflowTypeCache.All().Select(a => a.Id.ToString()).ToArray();
                    cacheAttributeList = cacheAttributeList
                                         .Where(a =>
                                                a.EntityTypeQualifierColumn == null ||
                                                a.EntityTypeQualifierColumn == string.Empty ||
                                                (a.EntityTypeQualifierColumn == "WorkflowTypeId" && validWorkflowTypeIds.Contains(a.EntityTypeQualifierValue))).ToList();
                }
                else
                {
                    cacheAttributeList = cacheAttributeList.Where(a => string.IsNullOrEmpty(a.EntityTypeQualifierColumn) && string.IsNullOrEmpty(a.EntityTypeQualifierValue)).ToList();
                }

                EntityHelper.AddEntityFieldsForAttributeList(entityFields, cacheAttributeList);
            }

            // Order the fields by title, name
            int index        = 0;
            var sortedFields = new List <EntityField>();

            foreach (var entityField in entityFields.OrderBy(p => !string.IsNullOrEmpty(p.AttributeEntityTypeQualifierName)).ThenBy(p => p.Title).ThenBy(p => p.Name))
            {
                entityField.Index = index;
                index++;
                sortedFields.Add(entityField);
            }

            if (HttpContext.Current != null)
            {
                HttpContext.Current.Items[EntityHelper.GetCacheKey(entityType, includeOnlyReportingFields, limitToFilterableFields)] = sortedFields;
            }

            return(sortedFields);
        }
Example #2
0
        /// <summary>
        /// Gets the entity fields for a specific Entity
        /// </summary>
        /// <param name="entityType">Type of the entity.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="includeOnlyReportingFields">if set to <c>true</c> [include only reporting fields].</param>
        /// <param name="limitToFilterableFields">if set to <c>true</c> [limit to filterable fields].</param>
        /// <returns></returns>
        private static List <EntityField> GetEntityFields(Type entityType, IEntity entity, bool includeOnlyReportingFields = true, bool limitToFilterableFields = true)
        {
            List <EntityField> entityFields = null;

            if (HttpContext.Current != null)
            {
                entityFields = HttpContext.Current.Items[EntityHelper.GetCacheKey(entityType, entity, includeOnlyReportingFields, limitToFilterableFields)] as List <EntityField>;
                if (entityFields != null)
                {
                    return(entityFields);
                }
            }

            if (entityFields == null)
            {
                entityFields = new List <EntityField>();
            }

            List <PropertyInfo> entityProperties = entityType.GetProperties().ToList();

            // filter the properties to narrow down the ones that we want to include in EntityFields
            var filteredEntityProperties = entityProperties
                                           .Where((p) =>
            {
                var includeForReportingAttribute = p.GetCustomAttribute <IncludeForReportingAttribute>() != null;

                // if the property has an IncludeForReportingAttribute, include it regardless
                if (includeForReportingAttribute)
                {
                    return(true);
                }

                // if marked as NotMapped, don't include it since it won't work in a LinqToEntity expression
                var notMapped = p.GetCustomAttribute <NotMappedAttribute>() != null;

                bool hideFromReporting = false;
                if (includeOnlyReportingFields)
                {
                    hideFromReporting = p.GetCustomAttribute <HideFromReportingAttribute>() != null;
                }

                // if the property has NotMappedAttribute or should be hidden from reporting, don't show it
                if (notMapped || hideFromReporting)
                {
                    return(false);
                }

                // if the property is marked virtual (unless it is 'virtual final'), don't include it since it isn't a real database field
                var getter    = p.GetGetMethod();
                var isVirtual = getter?.IsVirtual == true;
                if (isVirtual)
                {
                    // NOTE: Properties that implement interface members (for example Rock.Data.IOrder) will also be marked as 'virtual final' by the compiler, so check IsFinal to determine if it was the compiler that did it.
                    // See https://docs.microsoft.com/en-us/dotnet/api/system.reflection.methodbase.isfinal?redirectedfrom=MSDN&view=netframework-4.7.2#System_Reflection_MethodBase_IsFinal
                    bool isVirtualDueToInterface = getter?.IsFinal == true;
                    if (!isVirtualDueToInterface)
                    {
                        return(false);
                    }
                }

                return(true);
            }).ToList();

            // Go thru filteredEntityProperties and create the list of EntityFields that we can include
            foreach (var property in filteredEntityProperties)
            {
                EntityField entityField = new EntityField(property.Name, FieldKind.Property, property);
                entityField.IsPreviewable = property.GetCustomAttributes(typeof(PreviewableAttribute), true).Any();
                var fieldTypeAttribute = property.GetCustomAttribute <Rock.Data.FieldTypeAttribute>();

                // check if we can set it from the fieldTypeAttribute
                if ((fieldTypeAttribute != null) && SetEntityFieldFromFieldTypeAttribute(entityField, fieldTypeAttribute))
                {
                    // intentionally blank, entity field is already setup
                }

                // Enum Properties
                else if (property.PropertyType.IsEnum)
                {
                    entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.SINGLE_SELECT.AsGuid());

                    var list = new List <string>();
                    foreach (var value in Enum.GetValues(property.PropertyType))
                    {
                        list.Add(string.Format("{0}^{1}", value, value.ToString().SplitCase()));
                    }

                    var listSource = string.Join(",", list);
                    entityField.FieldConfig.Add("values", new Field.ConfigurationValue(listSource));
                    entityField.FieldConfig.Add("fieldtype", new Field.ConfigurationValue("rb"));
                }

                // Boolean properties
                else if (property.PropertyType == typeof(bool) || property.PropertyType == typeof(bool?))
                {
                    entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.BOOLEAN.AsGuid());
                }

                // Datetime properties
                else if (property.PropertyType == typeof(DateTime) || property.PropertyType == typeof(DateTime? ))
                {
                    var colAttr = property.GetCustomAttributes(typeof(ColumnAttribute), true).FirstOrDefault();
                    if (colAttr != null && (( ColumnAttribute )colAttr).TypeName == "Date")
                    {
                        entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.DATE.AsGuid());
                    }
                    else
                    {
                        entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.DATE_TIME.AsGuid());
                    }
                }

                // Decimal properties
                else if (property.PropertyType == typeof(decimal) || property.PropertyType == typeof(decimal? ))
                {
                    entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.DECIMAL.AsGuid());
                }

                // Text Properties
                else if (property.PropertyType == typeof(string))
                {
                    entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.TEXT.AsGuid());
                }

                // Integer Properties (which may be a DefinedValue)
                else if (property.PropertyType == typeof(int) || property.PropertyType == typeof(int?))
                {
                    entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.INTEGER.AsGuid());

                    var definedValueAttribute = property.GetCustomAttribute <Rock.Data.DefinedValueAttribute>();
                    if (definedValueAttribute != null)
                    {
                        // Defined Value Properties
                        Guid?definedTypeGuid = ((Rock.Data.DefinedValueAttribute)definedValueAttribute).DefinedTypeGuid;
                        if (definedTypeGuid.HasValue)
                        {
                            var definedType = DefinedTypeCache.Get(definedTypeGuid.Value);
                            entityField.Title = definedType != null ? definedType.Name : property.Name.Replace("ValueId", string.Empty).SplitCase();
                            if (definedType != null)
                            {
                                entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.DEFINED_VALUE.AsGuid());
                                entityField.FieldConfig.Add("definedtype", new Field.ConfigurationValue(definedType.Id.ToString()));
                            }
                        }
                    }
                }

                if (entityField != null && entityField.FieldType != null)
                {
                    entityFields.Add(entityField);
                }
            }

            // Get Attributes
            var entityTypeCache = EntityTypeCache.Get(entityType, true);

            if (entityTypeCache != null)
            {
                int entityTypeId = entityTypeCache.Id;
                List <AttributeCache> cacheAttributeList;
                if (entity != null)
                {
                    // if a specific entity is set, we only need to get the Attributes that the Entity has
                    if (entity is IHasAttributes)
                    {
                        (entity as IHasAttributes).LoadAttributes();
                        cacheAttributeList = (entity as IHasAttributes).Attributes.Select(a => a.Value).ToList();
                    }
                    else
                    {
                        cacheAttributeList = new List <AttributeCache>();
                    }
                }
                else
                {
                    using (var rockContext = new RockContext())
                    {
                        var qryAttributes = new AttributeService(rockContext).GetByEntityTypeId(entityTypeId);
                        if (entityType == typeof(Group) || entityType == typeof(GroupMember))
                        {
                            // in the case of Group or GroupMember, show attributes that are entity global, but also ones that are qualified by GroupTypeId
                            qryAttributes = qryAttributes
                                            .Where(a =>
                                                   a.EntityTypeQualifierColumn == null ||
                                                   a.EntityTypeQualifierColumn == string.Empty ||
                                                   a.EntityTypeQualifierColumn == "GroupTypeId");
                        }
                        else if (entityType == typeof(ContentChannelItem))
                        {
                            // in the case of ContentChannelItem, show attributes that are entity global, but also ones that are qualified by ContentChannelTypeId or ContentChannelId
                            qryAttributes = qryAttributes
                                            .Where(a =>
                                                   a.EntityTypeQualifierColumn == null ||
                                                   a.EntityTypeQualifierColumn == string.Empty ||
                                                   a.EntityTypeQualifierColumn == "ContentChannelTypeId" ||
                                                   a.EntityTypeQualifierColumn == "ContentChannelId"
                                                   );
                        }
                        else if (entityType == typeof(Rock.Model.Workflow))
                        {
                            // in the case of Workflow, show attributes that are entity global, but also ones that are qualified by WorkflowTypeId (and have a valid WorkflowTypeId)
                            var validWorkflowTypeIds = new WorkflowTypeService(rockContext).Queryable().Select(a => a.Id).ToList().Select(a => a.ToString()).ToList();
                            qryAttributes = qryAttributes
                                            .Where(a =>
                                                   a.EntityTypeQualifierColumn == null ||
                                                   a.EntityTypeQualifierColumn == string.Empty ||
                                                   (a.EntityTypeQualifierColumn == "WorkflowTypeId" && validWorkflowTypeIds.Contains(a.EntityTypeQualifierValue)));
                        }
                        else
                        {
                            qryAttributes = qryAttributes.Where(a => string.IsNullOrEmpty(a.EntityTypeQualifierColumn) && string.IsNullOrEmpty(a.EntityTypeQualifierValue));
                        }

                        cacheAttributeList = qryAttributes.ToAttributeCacheList();
                    }
                }

                foreach (var attributeCache in cacheAttributeList)
                {
                    AddEntityFieldForAttribute(entityFields, attributeCache, limitToFilterableFields);
                }
            }

            // Order the fields by title, name
            int index        = 0;
            var sortedFields = new List <EntityField>();

            foreach (var entityField in entityFields.OrderBy(p => !string.IsNullOrEmpty(p.AttributeEntityTypeQualifierName)).ThenBy(p => p.Title).ThenBy(p => p.Name))
            {
                entityField.Index = index;
                index++;
                sortedFields.Add(entityField);
            }

            if (HttpContext.Current != null)
            {
                HttpContext.Current.Items[EntityHelper.GetCacheKey(entityType, entity, includeOnlyReportingFields, limitToFilterableFields)] = sortedFields;
            }

            return(sortedFields);
        }
Example #3
0
        /// <summary>
        /// Gets the entity fields.
        /// </summary>
        /// <param name="entityType">Type of the entity.</param>
        /// <param name="includeOnlyReportingFields">if set to <c>true</c> [include only reporting fields].</param>
        /// <param name="limitToFilterableFields">if set to <c>true</c> [limit to filterable fields].</param>
        /// <returns></returns>
        public static List <EntityField> GetEntityFields(Type entityType, bool includeOnlyReportingFields = true, bool limitToFilterableFields = true)
        {
            List <EntityField> entityFields = null;

            _workflowTypeNameLookup = null;

            if (HttpContext.Current != null)
            {
                entityFields = HttpContext.Current.Items[EntityHelper.GetCacheKey(entityType, includeOnlyReportingFields, limitToFilterableFields)] as List <EntityField>;
                if (entityFields != null)
                {
                    return(entityFields);
                }
            }

            if (entityFields == null)
            {
                entityFields = new List <EntityField>();
            }

            // Find all non-virtual properties or properties that have the [IncludeForReporting] attribute
            var entityProperties         = entityType.GetProperties().ToList();
            var filteredEntityProperties = entityProperties
                                           .Where(p =>
                                                  !p.GetGetMethod().IsVirtual ||
                                                  p.GetCustomAttributes(typeof(IncludeForReportingAttribute), true).Any() ||
                                                  p.Name == "Order" || p.Name == "IsActive")
                                           .ToList();

            // Get Properties
            foreach (var property in filteredEntityProperties)
            {
                bool isReportable = !property.GetCustomAttributes(typeof(HideFromReportingAttribute), true).Any();
                if (!includeOnlyReportingFields || isReportable)
                {
                    EntityField entityField = new EntityField(property.Name, FieldKind.Property, property);
                    entityField.IsPreviewable = property.GetCustomAttributes(typeof(PreviewableAttribute), true).Any();
                    var fieldTypeAttribute = property.GetCustomAttribute <Rock.Data.FieldTypeAttribute>();

                    // check if we can set it from the fieldTypeAttribute
                    if ((fieldTypeAttribute != null) && SetEntityFieldFromFieldTypeAttribute(entityField, fieldTypeAttribute))
                    {
                        // intentially blank, entity field is already setup
                    }

                    // Enum Properties
                    else if (property.PropertyType.IsEnum)
                    {
                        entityField.FieldType = FieldTypeCache.Read(SystemGuid.FieldType.SINGLE_SELECT.AsGuid());

                        var list = new List <string>();
                        foreach (var value in Enum.GetValues(property.PropertyType))
                        {
                            list.Add(string.Format("{0}^{1}", value, value.ToString().SplitCase()));
                        }

                        var listSource = string.Join(",", list);
                        entityField.FieldConfig.Add("values", new Field.ConfigurationValue(listSource));
                        entityField.FieldConfig.Add("fieldtype", new Field.ConfigurationValue("rb"));
                    }

                    // Boolean properties
                    else if (property.PropertyType == typeof(bool) || property.PropertyType == typeof(bool?))
                    {
                        entityField.FieldType = FieldTypeCache.Read(SystemGuid.FieldType.BOOLEAN.AsGuid());
                    }

                    // Datetime properties
                    else if (property.PropertyType == typeof(DateTime) || property.PropertyType == typeof(DateTime? ))
                    {
                        var colAttr = property.GetCustomAttributes(typeof(ColumnAttribute), true).FirstOrDefault();
                        if (colAttr != null && ((ColumnAttribute)colAttr).TypeName == "Date")
                        {
                            entityField.FieldType = FieldTypeCache.Read(SystemGuid.FieldType.DATE.AsGuid());
                        }
                        else
                        {
                            entityField.FieldType = FieldTypeCache.Read(SystemGuid.FieldType.DATE_TIME.AsGuid());
                        }
                    }

                    // Decimal properties
                    else if (property.PropertyType == typeof(decimal) || property.PropertyType == typeof(decimal? ))
                    {
                        entityField.FieldType = FieldTypeCache.Read(SystemGuid.FieldType.DECIMAL.AsGuid());
                    }

                    // Text Properties
                    else if (property.PropertyType == typeof(string))
                    {
                        entityField.FieldType = FieldTypeCache.Read(SystemGuid.FieldType.TEXT.AsGuid());
                    }

                    // Integer Properties (which may be a DefinedValue)
                    else if (property.PropertyType == typeof(int) || property.PropertyType == typeof(int?))
                    {
                        entityField.FieldType = FieldTypeCache.Read(SystemGuid.FieldType.INTEGER.AsGuid());

                        var definedValueAttribute = property.GetCustomAttribute <Rock.Data.DefinedValueAttribute>();
                        if (definedValueAttribute != null)
                        {
                            // Defined Value Properties
                            Guid?definedTypeGuid = ((Rock.Data.DefinedValueAttribute)definedValueAttribute).DefinedTypeGuid;
                            if (definedTypeGuid.HasValue)
                            {
                                var definedType = DefinedTypeCache.Read(definedTypeGuid.Value);
                                entityField.Title = definedType != null ? definedType.Name : property.Name.Replace("ValueId", string.Empty).SplitCase();
                                if (definedType != null)
                                {
                                    entityField.FieldType = FieldTypeCache.Read(SystemGuid.FieldType.DEFINED_VALUE.AsGuid());
                                    entityField.FieldConfig.Add("definedtype", new Field.ConfigurationValue(definedType.Id.ToString()));
                                }
                            }
                        }
                    }

                    if (entityField != null && entityField.FieldType != null)
                    {
                        entityFields.Add(entityField);
                    }
                }
            }

            // Get Attributes
            var entityTypeCache = EntityTypeCache.Read(entityType, true);

            if (entityTypeCache != null)
            {
                int entityTypeId = entityTypeCache.Id;
                using (var rockContext = new RockContext())
                {
                    var qryAttributes = new AttributeService(rockContext).Queryable().Where(a => a.EntityTypeId == entityTypeId);
                    if (entityType == typeof(Group) || entityType == typeof(GroupMember))
                    {
                        // in the case of Group or GroupMember, show attributes that are entity global, but also ones that are qualified by GroupTypeId
                        qryAttributes = qryAttributes
                                        .Where(a =>
                                               a.EntityTypeQualifierColumn == null ||
                                               a.EntityTypeQualifierColumn == string.Empty ||
                                               a.EntityTypeQualifierColumn == "GroupTypeId");
                    }
                    else if (entityType == typeof(ContentChannelItem))
                    {
                        // in the case of ContentChannelItem, show attributes that are entity global, but also ones that are qualified by ContentChannelTypeId or ContentChannelId
                        qryAttributes = qryAttributes
                                        .Where(a =>
                                               a.EntityTypeQualifierColumn == null ||
                                               a.EntityTypeQualifierColumn == string.Empty ||
                                               a.EntityTypeQualifierColumn == "ContentChannelTypeId" ||
                                               a.EntityTypeQualifierColumn == "ContentChannelId"
                                               );
                    }
                    else if (entityType == typeof(Rock.Model.Workflow))
                    {
                        // in the case of Workflow, show attributes that are entity global, but also ones that are qualified by WorkflowTypeId (and have a valid WorkflowTypeId)
                        var validWorkflowTypeIds = new WorkflowTypeService(rockContext).Queryable().Select(a => a.Id).ToList().Select(a => a.ToString()).ToList();
                        qryAttributes = qryAttributes
                                        .Where(a =>
                                               a.EntityTypeQualifierColumn == null ||
                                               a.EntityTypeQualifierColumn == string.Empty ||
                                               (a.EntityTypeQualifierColumn == "WorkflowTypeId" && validWorkflowTypeIds.Contains(a.EntityTypeQualifierValue)));
                    }
                    else
                    {
                        qryAttributes = qryAttributes.Where(a => string.IsNullOrEmpty(a.EntityTypeQualifierColumn) && string.IsNullOrEmpty(a.EntityTypeQualifierValue));
                    }

                    var attributeIdList = qryAttributes.Select(a => a.Id).ToList();

                    foreach (var attributeId in attributeIdList)
                    {
                        AddEntityFieldForAttribute(entityFields, AttributeCache.Read(attributeId), limitToFilterableFields);
                    }
                }
            }

            // Order the fields by title, name
            int index        = 0;
            var sortedFields = new List <EntityField>();

            foreach (var entityField in entityFields.OrderBy(p => !string.IsNullOrEmpty(p.AttributeEntityTypeQualifierName)).ThenBy(p => p.Title).ThenBy(p => p.Name))
            {
                entityField.Index = index;
                index++;
                sortedFields.Add(entityField);
            }

            if (HttpContext.Current != null)
            {
                HttpContext.Current.Items[EntityHelper.GetCacheKey(entityType, includeOnlyReportingFields, limitToFilterableFields)] = sortedFields;
            }

            return(sortedFields);
        }