Table of Contents

Runtime metadata provider

The Neos framework provides a set of runtime metadata providers that enable applications to access detailed information about entities, entity views, UI views, enums, and lookups at runtime. These providers offer a way to introspect application metadata without relying on reflection or API documentation.

Overview

The metadata providers are designed to replace the need for:

  • C# reflection over entity types
  • Manual parsing of Swagger/OpenAPI JSON documentation
  • Hard-coded metadata in business logic

They are exposed through dependency injection and can be used throughout your application, particularly during data migrations, AI operations, and advanced business logic.

Core metadata providers

Entity metadata provider

IEntityMetadataProvider provides runtime access to entity metadata.

Key functionality:

  • EntitiesAssembly - The assembly containing all entity types
  • AllEntities - Dictionary of all entity names and their basic metadata
  • GetProperty(entityName) - Get properties metadata for a specific entity

Entity metadata includes:

  • Description - Functional description of the entity exposed through EntityMetadata

Property metadata includes:

  • Type - The .NET type of the property
  • Caption - Localized display name
  • AIDescription - Description for AI systems
  • PersonalData - Flag indicating if the property contains personal data
  • TableName - Associated database table name
  • ColumnName - Associated database column name

EntityMetadata

EntityMetadata is the runtime representation of an entity itself.

At the moment, it intentionally stays compact and exposes a single value:

  • Description - A textual description of the entity

This makes AllEntities useful for listing the available business entities and attaching a human-readable description to each one without loading CLR metadata through reflection.

EntityPropertyMetadata

EntityPropertyMetadata describes one property of an entity as generated from metadata.

It is the runtime object returned by GetProperty(entityName) and is the main entry point when business code needs to inspect entity fields dynamically.

Identity and typing:

  • Type - CLR type of the property, resolved from generated type information
  • Caption - Localized label associated with the property

Functional and AI-oriented metadata:

  • AIDescription - Additional semantic description intended for AI features or prompt construction
  • PersonalData - Boolean flag indicating whether the property is considered personal data

Database mapping metadata:

  • TableName - Physical table name when the property is persisted in a database table
  • ColumnName - Physical column name when the property is mapped to a database column

The database mapping fields are especially useful in migration or governance scenarios, because they connect business metadata back to the concrete persistence model. This is what enables the SetPersonalDataLabelCommand example later in this article to convert a PersonalData flag into database-specific column labeling.

The combination of PersonalData, TableName, and ColumnName is also a good illustration of the runtime provider's purpose: it exposes business intent and persistence details through one unified API, without requiring custom parsing of YAML files or direct inspection of generated entity classes.

Entity view descriptor

IEntityViewDescriptor provides metadata about entity views.

Key functionality:

  • GetAllEntityViewNames() - List all available entity views
  • GetEntityViewMetadata(entityViewName) - Get detailed metadata for a specific entity view

Entity view metadata includes:

  • Name - Entity view name
  • Description - Textual description
  • AIUsable - Whether the entity view can be used for AI operations
  • OpenApiModelBaseName - Base name for OpenAPI models
  • ScalarProperties - List of scalar property metadata
  • NavigationProperties - References and collections
  • AdditionnalDataProperties - Additional data fields

EntityViewMetadata

EntityViewMetadata is the runtime representation of one entity view.

It combines the global description of the entity view with the full inventory of scalar, navigation, and additional-data properties that the generated API exposes.

It includes the following fields:

  • Name - The entity view name
  • AIUsable - Whether the entity view can participate in AI-oriented features
  • Description - Functional description of the entity view
  • OpenApiModelBaseName - Base name used for the generated OpenAPI model
  • ScalarProperties - Scalar fields exposed as EntityViewPropertyMetadata
  • NavigationProperties - Reference and collection fields exposed as EntityViewNavigationPropertyMetadata
  • AdditionnalDataProperties - Extra property groups exposed as dictionaries of EntityViewPropertyMetadata

This makes EntityViewMetadata the main runtime entry point when you need to understand the contract of an entity view without inspecting generated DTO types or OpenAPI output.

EntityViewPropertyMetadata

EntityViewPropertyMetadata describes one scalar property exposed by an entity view.

Identity and typing:

  • Name - Property name in the entity view contract
  • Caption - Localized caption associated with the property
  • DataType - High-level data type used by Neos metadata
  • EnumTypeName - Enum type name when the property uses an enum data type

Validation and semantics:

  • Required - Whether the property is mandatory
  • IsKey - Whether the property is part of the entity view key
  • AIDescription - Semantic description intended for AI features
  • DefaultValue - Default value serialized as a string representation

Formatting constraints:

  • Format - Format string associated with the property
  • MaxLength - Maximum length for string properties
  • Scale - Number of digits to the right of the decimal point for decimal properties

UI mapping:

  • UIViewProperties - Optional dictionary that maps this entity-view property to UI-view-specific property metadata

UIViewProperties is especially useful when you want to bridge backend entity-view metadata with the way the same field is configured in generated UI views.

EntityViewNavigationPropertyMetadata

EntityViewNavigationPropertyMetadata describes a navigation property of an entity view, meaning either a reference to entity view or a collection of embedded entity views.

It exposes the following information:

  • Name - Navigation property name
  • Caption - Localized caption for the navigation property
  • RelatedEntityViewName - Name of the entity view targeted by the relation
  • RelationType - Relation kind, typically Reference or Collection
  • AIDescription - Semantic description for AI-related scenarios
  • UIViewProperties - Optional dictionary of UI-specific metadata attached to this navigation property

This metadata is what allows runtime consumers to reconstruct the graph of entity-view relationships. It is also the missing piece when a custom tool needs to distinguish scalar fields from expandable references and collections.

Additional data properties

AdditionnalDataProperties stores groups of extra scalar properties that do not belong to the main scalar property list.

Each dictionary entry is keyed by a logical group name and contains a list of EntityViewPropertyMetadata. This is useful when an entity view exposes computed or contextual data alongside its main contract and that data still needs the same runtime description model.

UI view descriptor

IUIViewDescriptor provides metadata about UI views.

Key functionality:

  • GetAllUIViewNames() - List all available UI views
  • GetUIViewMetadata(uiViewName) - Get metadata for a specific UI view
  • GetUIViewNames(entityViewName) - Find all UI views associated with an entity view

UI view metadata includes:

  • Name - UI view name
  • AIUsable - Whether the UI view can be used by AI-oriented features
  • EntityViewName - Associated entity view, when the UI view is bound to one
  • Description - Textual description of the UI view
  • Properties - Field-level metadata exposed as UIViewPropertyMetadata
  • SubUIViews - Child UI views exposed as UIViewSubUIViewMetadata

UIViewMetadata

UIViewMetadata is the runtime entry point for inspecting a single UI view.

It gives access to both the overall definition of the view and the elements needed to render or analyze it:

  • Name identifies the UI view.
  • AIUsable indicates whether the UI view can participate in AI features.
  • EntityViewName links the UI view back to the entity view it represents.
  • Description contains the functional description generated from metadata.
  • Properties lists the fields available in the UI view.
  • SubUIViews lists nested UI views attached to the current one.

This makes UIViewMetadata useful when you need to inspect a screen definition without parsing XML templates directly.

UIViewPropertyMetadata

UIViewPropertyMetadata describes one property rendered or managed by a UI view.

It combines functional metadata, visibility rules, datagrid settings, filter behavior, and AI-related settings.

Identity and typing:

  • Name - Property name in the UI view
  • Caption - Localized label shown to users
  • DataType - High-level UI data type
  • EnumTypeName - Enum type name when DataType is enum-based
  • IsKey - Whether the property is part of the key

Editability and validation:

  • ReadOnly - Constant read-only state when it can be resolved at generation time
  • Required - Constant required state when it can be resolved at generation time
  • DefaultValue - Default value used by the UI or AI evaluation pipeline
  • CharacterCasing - Character casing behavior applied to the field

Visibility and navigation:

  • FormVisible - Whether the property is visible in forms
  • DatagridVisible - Whether the property is visible in data grids
  • TabStop - Whether the property participates in tab navigation

Datagrid configuration:

  • DatagridCaption - Caption specifically used in the data grid
  • DatagridWidth - Column width
  • DatagridPosition - Zero-based column order
  • DatagridFrozen - Whether the column is frozen
  • DatagridMovable - Whether the column can be moved
  • Ellipsis - Whether overflowing content uses ellipsis rendering

Filtering metadata:

  • DefaultFilterOperator - Default operator offered by filtering features
  • FilterVisible - Whether filtering is enabled for the property
  • FilterVisibleInPanel - Whether the filter appears in the filter panel
  • FilterPosition - Zero-based filter order

AI-assisted input:

  • AIAutoSuggestPrompt - Prompt template used to generate suggestions
  • AIAutoSuggestTriggers - List of properties that trigger suggestion recomputation

Several boolean properties are nullable because the generator only emits a value when the metadata can be resolved as a constant. A null value means the runtime metadata cannot guarantee a fixed value for that setting.

UIViewSubUIViewMetadata

UIViewSubUIViewMetadata describes a child UI view declared inside a parent UI view.

It exposes two pieces of information:

  • Name - The name of the nested UI view
  • RelationPropertyName - The property on the parent UI view that defines the relation with that child

This is the runtime link that allows tooling or custom logic to reconstruct the composition of complex UI screens, such as a master-detail form with embedded collections or referenced child views.

Enum metadata provider

IEnumMetadataProvider provides metadata about enums.

Key functionality:

  • AllEnums - Dictionary of all enum types and their metadata
  • GetEnumMembers(enumName) - Get members of a specific enum (also available as generic method)
  • GetEnumMembers<TEnum>() - Type-safe generic method to get enum members

Enum metadata includes:

  • Description - Functional description of the enum exposed through EnumTypeMetadata
  • Members - Member list exposed through EnumMemberMetadata

EnumTypeMetadata

EnumTypeMetadata is the runtime representation of an enum type.

Like EntityMetadata, it intentionally stays compact and currently exposes a single field:

  • Description - Textual description of the enum type

This makes AllEnums useful when you need to list the available business enums and attach a human-readable explanation to each one without reflecting over CLR enum types directly.

EnumMemberMetadata

EnumMemberMetadata describes one member of an enum exposed by the runtime metadata provider.

It includes the following fields:

  • Name - The enum member name as exposed in the generated model
  • Caption - Optional localized label associated with that member

This is the metadata consumed when a runtime feature needs to present enum values to users, generate documentation, or feed a UI component with values that are both stable for code and readable for humans.

The combination of EnumTypeMetadata and EnumMemberMetadata gives access to both the semantic description of the enum and the user-facing representation of each possible value.

For information about defining enum types, configuring persistence, and using enum metadata in server or UI code, see Enum type.

Lookup metadata provider

ILookupMetadataProvider provides metadata about lookups.

Key functionality:

  • AllLookups - Dictionary of all lookup configurations and their metadata

Lookup metadata includes:

  • UIViewName - Target UI view used by the lookup
  • MainMode - Main interaction mode associated with the lookup
  • ValueProperty - Persisted property returned by the lookup
  • DisplayProperty - Property displayed to users

LookupMetadata

LookupMetadata is the runtime representation of one lookup configuration.

It exposes the following fields:

  • UIViewName - Name of the UI view opened or used by the lookup
  • MainMode - Main mode associated with that UI view in the lookup scenario
  • ValueProperty - Property whose value is persisted when the user selects a lookup entry
  • DisplayProperty - Property shown to the user as the readable display value

This model is intentionally compact. It focuses on the information needed to bind a lookup field to a UI view and to distinguish between the stored value and the displayed label.

At runtime, this allows a consumer to answer questions such as:

  • Which UI view backs this lookup?
  • Which field is stored in the underlying model?
  • Which field should be shown to the user?

That makes LookupMetadata useful for generated forms, custom tooling, and any runtime feature that needs to understand how lookup inputs are wired without re-reading YAML metadata.

Practical example: Classifying sensitive data

The TechnicalDemos cluster includes a practical example of using the entity metadata provider to automatically classify personal data in the database during migrations.

Scenario

The Person module metadata defines properties marked with the PersonalData flag:

- Name: SocialSecurityNumber
  Caption: Social security number
  PersonalData: true
- Name: FirstName
  Caption: First name
  PersonalData: true
- Name: LastName
  Caption: Last name
  PersonalData: true
- Name: BirthDate
  Caption: Birth date
  DataType: Date
  PersonalData: true

Implementation

The SetPersonalDataLabelCommand migration command uses the entity metadata provider to:

  1. Iterate through all entities in the application
  2. For each entity, retrieve its properties metadata
  3. Identify properties marked as personal data
  4. Apply database-specific sensitivity labels
public class SetPersonalDataLabelCommand : ICommand
{
    private readonly IEntityMetadataProvider _entityMetadataProvider;

    public SetPersonalDataLabelCommand(IEntityMetadataProvider entityMetadataProvider)
    {
        _entityMetadataProvider = entityMetadataProvider;
    }

    public void Execute(FluentMigrator.Migration migration, ICommandExecutionArgs args)
    {
        foreach (string entityName in _entityMetadataProvider.AllEntities.Keys)
        {
            IDictionary<string, EntityPropertyMetadata> properties =
                _entityMetadataProvider.GetProperty(entityName);

            foreach (EntityPropertyMetadata property in properties.Select(kvp => kvp.Value))
            {
                if (!property.PersonalData ||
                    string.IsNullOrEmpty(property.TableName) ||
                    string.IsNullOrEmpty(property.ColumnName))
                {
                    continue;
                }

                migration.SetPersonalDataLabel(
                    property.TableName,
                    property.ColumnName,
                    args);
            }
        }
    }
}

Database-specific implementation

The sensitivity classification adapts to the target database:

SQL Server: Uses sys.sensitivity_classifications to add sensitivity labels:

ADD SENSITIVITY CLASSIFICATION TO
[dbo].[Person].[SocialSecurityNumber]
WITH
(
    LABEL = 'PERSONAL_DATA',
    INFORMATION_TYPE = 'GDPR'
)

Oracle: Add comments to columns:

COMMENT ON COLUMN schema.table.column IS 'GDPR:PERSONAL_DATA'

PostgreSQL: Two strategies are available depending on your security infrastructure:

PostgreSQL without a security label provider — Use column comments:

COMMENT ON COLUMN schema.table.column IS 'GDPR:PERSONAL_DATA'

This approach requires no additional setup and works on any PostgreSQL instance. The comment is accessible via the pg_description catalog or the obj_description() function.

PostgreSQL with a security label provider — Use the SECURITY LABEL FOR syntax when a provider is installed (e.g., anon for anonymization):

/// <summary>
/// Applies a personal data security label to the specified PostgreSQL column using the <c>SECURITY LABEL FOR</c> syntax.
/// </summary>
/// <param name="migration">The migration instance.</param>
/// <param name="tableName">The name of the table containing the column.</param>
/// <param name="columnName">The name of the column to label.</param>
/// <param name="providerName">The name of the security label provider (e.g. <c>anon</c>).</param>
/// <remarks>
/// <para>
/// The security label provider must be loaded in PostgreSQL before calling this method.
/// Ensure the provider extension is installed and loaded via <c>CREATE EXTENSION</c>.
/// </para>
/// <para>
/// The system view <see href="https://www.postgresql.org/docs/current/view-pg-seclabels.html"><c>pg_seclabels</c></see> provides information about all assigned security labels across all providers.
/// </para>
/// </remarks>
public static void SetPostgreSqlPersonalDataSecurityLabel(
    this FluentMigrator.Migration migration,
    string tableName,
    string columnName,
    string providerName)
{
    migration.Execute.Sql($@"SECURITY LABEL FOR {providerName}
ON COLUMN ""{tableName}"".""{columnName}""
IS 'GDPR:PERSONAL_DATA'");
}

This approach is more robust when a security policy provider is deployed and allows fine-grained control over which operations are restricted based on labels.

Key considerations

Lazy loading and caching

Metadata providers use lazy loading with internal caching:

  • Metadata is loaded from embedded JSON resources on first access
  • Subsequent queries use cached data for performance
  • This approach minimizes memory usage and startup time

Metadata generation

Metadata is generated at build time by the Neos code generator:

  • The EntityMetadataProviderBase, EntityViewDescriptorBase, UIViewDescriptorBase, EnumMetadataProviderBase, and LookupMetadataProviderBase base classes load pre-generated JSON resources
  • Generated implementations in your business assemblies override the ResourceName and ResourceAssembly properties
  • Metadata is serialized using camelCase naming convention

Use cases

Data migration and transformation

Access property metadata to identify sensitive fields, required properties, or type information during complex data migrations.

AI and automation

Use entity view metadata with the AIUsable flag to determine which entity views can be processed by AI operations.

Dynamic validation

Implement custom validation logic that adapts based on property metadata like the PersonalData flag.

API documentation

Generate or enhance API documentation by accessing structured metadata about entity views and their properties.

Data classification and governance

Automatically classify, mask, or label sensitive data based on metadata annotations like PersonalData.

See also