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
ReferenceorCollection - 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
DataTypeis 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:
- Iterate through all entities in the application
- For each entity, retrieve its properties metadata
- Identify properties marked as personal data
- 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, andLookupMetadataProviderBasebase classes load pre-generated JSON resources - Generated implementations in your business assemblies override the
ResourceNameandResourceAssemblyproperties - 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.