Get the FREE Ultimate OpenClaw Setup Guide →

orchardcore-features

Scanned
npx machina-cli add skill CrestApps/CrestApps.AgentSkills/orchardcore-features --openclaw
Files (1)
SKILL.md
17.1 KB

OrchardCore Features

The OrchardCore.Features module provides the administrative interface and programmatic APIs for managing features within an Orchard Core application. Features are the fundamental units of functionality — each module exposes one or more features that can be independently enabled or disabled per tenant.

Enabling the Features Module

The OrchardCore.Features feature is typically enabled by default in most Orchard Core setups. It powers the Configuration → Features page in the admin dashboard. If it is not enabled, add it through a recipe or enable it programmatically.

Feature Management from the Admin Dashboard

Navigate to Configuration → Features in the admin panel to see a list of all available features. Each entry displays the feature name, description, category, and current state (enabled or disabled). Use the Enable or Disable buttons to toggle individual features. When enabling a feature that has dependencies, Orchard Core automatically resolves and enables the required dependencies first. Similarly, disabling a feature prompts a warning if other enabled features depend on it.

Programmatic Feature Control with IShellFeaturesManager

Use IShellFeaturesManager to enable or disable features from code. This service is registered in the dependency injection container and provides methods for querying and modifying feature states.

Querying Feature States

public sealed class FeatureStatusChecker
{
    private readonly IShellFeaturesManager _shellFeaturesManager;

    public FeatureStatusChecker(IShellFeaturesManager shellFeaturesManager)
    {
        _shellFeaturesManager = shellFeaturesManager;
    }

    public async Task<bool> IsFeatureEnabledAsync(string featureId)
    {
        var enabledFeatures = await _shellFeaturesManager.GetEnabledFeaturesAsync();

        return enabledFeatures.Any(f => f.Id == featureId);
    }

    public async Task<IEnumerable<string>> GetDisabledFeatureIdsAsync()
    {
        var disabledFeatures = await _shellFeaturesManager.GetDisabledFeaturesAsync();

        return disabledFeatures.Select(f => f.Id);
    }
}

Enabling and Disabling Features

public sealed class FeatureToggleService
{
    private readonly IShellFeaturesManager _shellFeaturesManager;

    public FeatureToggleService(IShellFeaturesManager shellFeaturesManager)
    {
        _shellFeaturesManager = shellFeaturesManager;
    }

    public async Task EnableFeaturesAsync(IEnumerable<IFeatureInfo> features, bool force = false)
    {
        // The force parameter controls whether to bypass dependency validation.
        await _shellFeaturesManager.EnableFeaturesAsync(features, force);
    }

    public async Task DisableFeaturesAsync(IEnumerable<IFeatureInfo> features, bool force = false)
    {
        // The force parameter controls whether to disable even if dependents exist.
        await _shellFeaturesManager.DisableFeaturesAsync(features, force);
    }
}

Retrieving Available Features

public sealed class FeatureCatalogService
{
    private readonly IShellFeaturesManager _shellFeaturesManager;

    public FeatureCatalogService(IShellFeaturesManager shellFeaturesManager)
    {
        _shellFeaturesManager = shellFeaturesManager;
    }

    public async Task<IEnumerable<IFeatureInfo>> GetAvailableFeaturesAsync()
    {
        return await _shellFeaturesManager.GetAvailableFeaturesAsync();
    }
}

Feature Dependencies and Dependency Resolution

Features can declare dependencies on other features in the module manifest (Manifest.cs). When a feature is enabled, Orchard Core walks the dependency graph and enables all required features in the correct order.

[assembly: Feature(
    id: "MyModule.Reporting",
    name: "Reporting",
    description: "Provides reporting dashboards.",
    category: "Content",
    dependencies:
    [
        "OrchardCore.Contents",
        "OrchardCore.Queries"
    ]
)]

In this example, enabling MyModule.Reporting automatically enables OrchardCore.Contents and OrchardCore.Queries if they are not already enabled. Circular dependencies are not permitted and result in a startup error.

Conditional Service Registration with RequireFeatures

The [RequireFeatures] attribute restricts a Startup class so that its services are only registered when the specified features are enabled. This is useful for optional integrations between modules.

[RequireFeatures("OrchardCore.Search.Lucene")]
public sealed class LuceneIntegrationStartup : StartupBase
{
    public override void ConfigureServices(IServiceCollection services)
    {
        // These services are only registered when OrchardCore.Search.Lucene is enabled.
        services.AddScoped<ILuceneQueryProvider, CustomLuceneQueryProvider>();
    }
}

You can specify multiple features. All listed features must be enabled for the Startup class to activate:

[RequireFeatures("OrchardCore.Contents", "OrchardCore.Workflows")]
public sealed class ContentWorkflowStartup : StartupBase
{
    public override void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IWorkflowTask, PublishContentTask>();
    }
}

Feature Event Handlers

Implement IFeatureEventHandler to execute custom logic when features are enabled or disabled. This is useful for running data migrations, seeding initial data, or performing cleanup.

public sealed class SampleFeatureEventHandler : IFeatureEventHandler
{
    private readonly ILogger<SampleFeatureEventHandler> _logger;

    public SampleFeatureEventHandler(ILogger<SampleFeatureEventHandler> logger)
    {
        _logger = logger;
    }

    public Task EnablingAsync(IFeatureInfo feature)
    {
        // Runs before the feature is enabled.
        return Task.CompletedTask;
    }

    public Task EnabledAsync(IFeatureInfo feature)
    {
        _logger.LogInformation("Feature '{FeatureId}' has been enabled.", feature.Id);

        return Task.CompletedTask;
    }

    public Task DisablingAsync(IFeatureInfo feature)
    {
        // Runs before the feature is disabled.
        return Task.CompletedTask;
    }

    public Task DisabledAsync(IFeatureInfo feature)
    {
        _logger.LogInformation("Feature '{FeatureId}' has been disabled.", feature.Id);

        return Task.CompletedTask;
    }

    public Task InstallingAsync(IFeatureInfo feature)
    {
        // Runs before a feature is installed for the first time.
        return Task.CompletedTask;
    }

    public Task InstalledAsync(IFeatureInfo feature)
    {
        _logger.LogInformation("Feature '{FeatureId}' has been installed.", feature.Id);

        return Task.CompletedTask;
    }

    public Task UninstallingAsync(IFeatureInfo feature)
    {
        return Task.CompletedTask;
    }

    public Task UninstalledAsync(IFeatureInfo feature)
    {
        return Task.CompletedTask;
    }
}

Register the event handler in your module's Startup class:

public sealed class Startup : StartupBase
{
    public override void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IFeatureEventHandler, SampleFeatureEventHandler>();
    }
}

Enabling Features via Recipes

Use the feature recipe step to enable or disable features as part of a site setup recipe or a standalone recipe.

Enabling Features

{
  "steps": [
    {
      "name": "feature",
      "enable": [
        "OrchardCore.Contents",
        "OrchardCore.ContentTypes",
        "OrchardCore.Title",
        "OrchardCore.Media",
        "OrchardCore.Users",
        "OrchardCore.Roles"
      ]
    }
  ]
}

Disabling Features

{
  "steps": [
    {
      "name": "feature",
      "disable": [
        "OrchardCore.Search.Lucene"
      ]
    }
  ]
}

Enabling and Disabling in a Single Step

{
  "steps": [
    {
      "name": "feature",
      "enable": [
        "OrchardCore.Search.Elasticsearch"
      ],
      "disable": [
        "OrchardCore.Search.Lucene"
      ]
    }
  ]
}

Feature Guards and Always-On Features

Some features are marked as always enabled and cannot be disabled. These are foundational features that the system depends on (e.g., OrchardCore.Settings). This is declared in the manifest:

[assembly: Feature(
    id: "OrchardCore.Settings",
    name: "Settings",
    description: "Provides site-level settings.",
    isAlwaysEnabled: true
)]

Custom modules can also declare features as always-on if they provide critical infrastructure that should never be turned off.

A feature guard is a pattern where you check at runtime whether a feature is enabled before executing logic:

public sealed class ConditionalContentHandler : ContentHandlerBase
{
    private readonly IShellFeaturesManager _shellFeaturesManager;

    public ConditionalContentHandler(IShellFeaturesManager shellFeaturesManager)
    {
        _shellFeaturesManager = shellFeaturesManager;
    }

    public override async Task PublishedAsync(PublishContentContext context)
    {
        var enabledFeatures = await _shellFeaturesManager.GetEnabledFeaturesAsync();

        if (!enabledFeatures.Any(f => f.Id == "OrchardCore.Notifications"))
        {
            return;
        }

        // Perform notification logic only when OrchardCore.Notifications is enabled.
    }
}

However, the preferred approach is to use [RequireFeatures] on a Startup class rather than runtime guards, as it avoids unnecessary service resolution.

Listing Available Features per Tenant

Each tenant in a multi-tenant Orchard Core application has its own set of enabled features. Use the admin dashboard or IShellFeaturesManager to inspect the feature state for the current tenant.

public sealed class TenantFeatureReporter
{
    private readonly IShellFeaturesManager _shellFeaturesManager;
    private readonly ShellSettings _shellSettings;

    public TenantFeatureReporter(
        IShellFeaturesManager shellFeaturesManager,
        ShellSettings shellSettings)
    {
        _shellFeaturesManager = shellFeaturesManager;
        _shellSettings = shellSettings;
    }

    public async Task<TenantFeatureSummary> GetSummaryAsync()
    {
        var enabled = await _shellFeaturesManager.GetEnabledFeaturesAsync();
        var disabled = await _shellFeaturesManager.GetDisabledFeaturesAsync();

        return new TenantFeatureSummary
        {
            TenantName = _shellSettings.Name,
            EnabledCount = enabled.Count(),
            DisabledCount = disabled.Count(),
            EnabledFeatureIds = enabled.Select(f => f.Id).OrderBy(id => id),
            DisabledFeatureIds = disabled.Select(f => f.Id).OrderBy(id => id),
        };
    }
}

public sealed class TenantFeatureSummary
{
    public string TenantName { get; set; }
    public int EnabledCount { get; set; }
    public int DisabledCount { get; set; }
    public IEnumerable<string> EnabledFeatureIds { get; set; }
    public IEnumerable<string> DisabledFeatureIds { get; set; }
}

Feature Catalog

Below is a catalog of commonly used OrchardCore features organized by category. Enable these feature IDs via the admin dashboard, recipes, or IShellFeaturesManager.

Content Management

Feature IDDescription
OrchardCore.ContentsCore content management system for creating, editing, publishing, and versioning content items.
OrchardCore.ContentTypesAdmin UI for defining and editing content type definitions, parts, and fields.
OrchardCore.TitleAdds a title part to content items.
OrchardCore.AliasProvides an alias part for assigning URL-friendly identifiers to content items.
OrchardCore.AutorouteAutomatically generates URL routes for content items based on configurable patterns.
OrchardCore.HtmlAdds an HTML body part for rich-text content editing.
OrchardCore.MarkdownAdds a Markdown body part for Markdown-based content editing.
OrchardCore.ListsEnables list functionality for organizing content items in ordered collections.
OrchardCore.TaxonomiesProvides taxonomy management for categorizing content with hierarchical terms.
OrchardCore.FlowsAllows building content layouts using a flow of widgets and content items.
OrchardCore.ContentFieldsAdds a library of reusable fields (text, numeric, boolean, date, link, etc.) to content types.
OrchardCore.ContentLocalizationEnables localization of content items into multiple cultures.
OrchardCore.IndexingProvides content indexing infrastructure used by search modules.
OrchardCore.PublishLaterAllows scheduling content items for future publication.

Media

Feature IDDescription
OrchardCore.MediaCore media management for uploading, organizing, and serving media files.
OrchardCore.MediaLibraryProvides a media library UI for browsing and selecting media assets.
OrchardCore.Media.IndexingEnables indexing of media file metadata for search.

Navigation

Feature IDDescription
OrchardCore.MenuProvides menu content types and rendering for site navigation.
OrchardCore.NavigationCore navigation infrastructure for building and managing navigation menus.
OrchardCore.SitemapsGenerates XML sitemaps for search engine optimization.

Security and Users

Feature IDDescription
OrchardCore.UsersUser registration, authentication, and profile management.
OrchardCore.RolesRole-based authorization and role management.
OrchardCore.OpenIdOpenID Connect server and client support for authentication.
OrchardCore.Users.TwoFactorAuthenticationAdds two-factor authentication support for user accounts.

Search

Feature IDDescription
OrchardCore.SearchCore search infrastructure providing a unified search API.
OrchardCore.Search.LuceneFull-text search powered by Lucene.NET.
OrchardCore.Search.ElasticsearchFull-text search powered by Elasticsearch.
OrchardCore.QueriesQuery engine for defining and executing named queries.

Workflows

Feature IDDescription
OrchardCore.WorkflowsVisual workflow engine for automating processes with activities and events.
OrchardCore.Workflows.HttpAdds HTTP request and response activities to workflows.
OrchardCore.Workflows.TimersAdds timer-based triggers for scheduling workflow execution.

Email and Notifications

Feature IDDescription
OrchardCore.EmailCore email sending infrastructure with SMTP support.
OrchardCore.NotificationsIn-app notification system for delivering messages to users.

Theming and Display

Feature IDDescription
OrchardCore.ThemesTheme management for selecting and configuring site themes.
OrchardCore.TemplatesLiquid template overrides for customizing shape rendering.
OrchardCore.LayersConditional widget layer rules for displaying content in zones based on conditions.
OrchardCore.WidgetsWidget content types for placing content in layout zones.

Localization

Feature IDDescription
OrchardCore.LocalizationProvides localization infrastructure for translating the admin UI and front-end.
OrchardCore.ContentLocalizationEnables localization of content items into multiple cultures.

Infrastructure

Feature IDDescription
OrchardCore.SettingsSite-level settings management (always enabled).
OrchardCore.RecipesRecipe infrastructure for importing and exporting site configuration.
OrchardCore.TenantsMulti-tenancy support for running isolated sites from a single application.
OrchardCore.BackgroundTasksBackground task scheduling and execution.
OrchardCore.ScriptingScripting engine for executing dynamic expressions in recipes and workflows.
OrchardCore.DynamicCacheShape-level output caching for improved rendering performance.
OrchardCore.ResponseCompressionEnables HTTP response compression (Gzip, Brotli).
OrchardCore.HealthChecksASP.NET Core health check endpoints for monitoring application status.

Data and Queries

Feature IDDescription
OrchardCore.QueriesQuery engine for defining reusable named queries.
OrchardCore.Queries.SqlSQL-based query provider for running SQL queries against the database.
OrchardCore.GraphQLGraphQL API endpoint for querying content and site data.
OrchardCore.Apis.GraphQLExposes a GraphQL API for content and resource queries.

SEO and Social

Feature IDDescription
OrchardCore.SeoSEO meta tags and canonical URL management.
OrchardCore.SitemapsXML sitemap generation for search engines.
OrchardCore.ReCaptchaGoogle reCAPTCHA integration for form protection.

Source

git clone https://github.com/CrestApps/CrestApps.AgentSkills/blob/main/src/CrestApps.AgentSkills/orchardcore/orchardcore-features/SKILL.mdView on GitHub

Overview

OrchardCore.Features provides the admin UI (Configuration → Features) and APIs to enable/disable tenant features. It covers dependencies, programmatic control with IShellFeaturesManager, recipe-based activation, and a categorized catalog of common features.

How This Skill Works

Features are modular units exposed by each module and can be toggled independently. The admin UI automatically resolves dependencies when enabling a feature, and warns when disabling a feature with dependents. Programmers can query and modify feature states via IShellFeaturesManager, with methods like GetEnabledFeaturesAsync, EnableFeaturesAsync, DisableFeaturesAsync, and GetAvailableFeaturesAsync.

When to Use It

  • Setting up a new Orchard Core app and selecting feature modules via the admin UI or recipes
  • Automating tenant provisioning where specific features must be enabled in a defined order
  • Programmatically auditing or adjusting feature states across tenants in code
  • Resolving feature dependency issues during deployment or runtime configuration
  • Exploring the feature catalog to understand available capabilities by category

Quick Start

  1. Step 1: Ensure the OrchardCore.Features module is enabled (default in most setups) or enable it via a recipe
  2. Step 2: Inject IShellFeaturesManager and call GetEnabledFeaturesAsync or GetAvailableFeaturesAsync to inspect state
  3. Step 3: Call EnableFeaturesAsync or DisableFeaturesAsync to toggle features, respecting dependencies

Best Practices

  • Rely on the built-in dependency resolution when enabling features to avoid broken configurations
  • Use the force option sparingly when bypassing dependency validation or to disable dependents
  • Prefer recipe-based activation for consistent, repeatable setups
  • Validate feature readiness before enabling in production (e.g., required modules, dependencies)
  • Log feature state changes and audit enabled/disabled features with IShellFeaturesManager APIs

Example Use Cases

  • Check if a feature is enabled using IsFeatureEnabledAsync in a FeatureStatusChecker
  • Enable or disable features from code with EnableFeaturesAsync and DisableFeaturesAsync in a FeatureToggleService
  • List available features via GetAvailableFeaturesAsync in a FeatureCatalogService
  • Rely on UI toggles in Configuration → Features to auto-resolve dependencies when enabling
  • Query disabled feature IDs using GetDisabledFeaturesAsync for auditing

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers