orchardcore-modules
Skill for creating and structuring Orchard Core modules. Covers module scaffolding, feature registration, dependency management, startup configuration, and manifest conventions.
Files2
View on GitHubSKILL.mdsrc/CrestApps.AgentSkills/orchardcore/orchardcore-modules/SKILL.md
GitHubOrchard Core Modules - Prompt Templates
Create a Module
You are an Orchard Core expert. Generate the scaffolding for a module owned by
an application that consumes Orchard Core packages. For the full code
templates (parts, fields, drivers, handlers, admin pages, the ocmodulecms
project template), use the orchardcore-module-creator skill alongside this
one.
Guidelines
- Module names should be PascalCase and typically prefixed with the organization name (e.g.,
MyOrg.MyModule). - Every module must have a
Manifest.csfile declaring its features. - Each feature must have a unique ID and should declare its dependencies (feature IDs such as
OrchardCore.Contents, not package names). - Use
Startupclasses to register services, routes, and navigation. - Register migrations with
services.AddDataMigration<Migrations>(). - Declare a new feature with
[assembly: Feature(...)]only when the user should manage it; to extend or override behavior when other features are present, gate aStartupwith[RequireFeatures(...)]instead of adding another feature the user must enable. See theorchardcore-featuresskill for the full decision. [Feature("Id")]on a startup or component may only name a feature declared by the same module; otherwise theOCSG002analyzer warns and the target is ignored at runtime. Use[RequireFeatures]for other modules' features.- Use
[RequiredStartup](4.0) for a component that must be composed for every tenant, even when its own feature is disabled. - Third-party modules (CrestApps, Lombiq, or any non-OrchardCore-direct modules) must be installed as NuGet packages or project references in the web project (the startup project of the solution), not just in the module project.
- Name configuration sections
OrchardCore:MyService[:Provider], without anOrchardCore_prefix (seeorchardcore-configuration). - Always seal classes, except view models.
Installing Third-Party Modules
Third-party modules are installed by adding NuGet packages or project references to the web project:
<Project Sdk="Microsoft.NET.Sdk.Web">
<ItemGroup>
<!-- Orchard Core base -->
<PackageReference Include="OrchardCore.Application.Cms.Targets" Version="3.*" />
<!-- Third-party modules must be in the web project -->
<PackageReference Include="Lombiq.HelpfulExtensions.OrchardCore" Version="1.*" />
</ItemGroup>
</Project>
For local module projects:
<ItemGroup>
<ProjectReference Include="../ThirdParty.Module/ThirdParty.Module.csproj" />
</ItemGroup>
Manifest Pattern
using OrchardCore.Modules.Manifest;
[assembly: Module(
Name = "{{ModuleName}}",
Author = "{{Author}}",
Website = "{{Website}}",
Version = "1.0.0",
Description = "{{Description}}",
Category = "{{Category}}"
)]
[assembly: Feature(
Id = "{{ModuleName}}",
Name = "{{FeatureName}}",
Description = "{{FeatureDescription}}",
Dependencies =
[
"OrchardCore.Contents",
],
Category = "{{Category}}"
)]
Startup Pattern
using Microsoft.Extensions.DependencyInjection;
using OrchardCore.Modules;
namespace {{ModuleName}};
public sealed class Startup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
// Register services here
}
}
// Only composed when the Workflows feature is enabled.
[RequireFeatures("OrchardCore.Workflows")]
public sealed class WorkflowsStartup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
// Register workflow activities here
}
}
Feature Targeting Attributes
| Attribute | Use it to |
|---|---|
[Feature("MyModule.Extra")] |
Attach a startup/component to a feature declared in this module's Manifest.cs. |
[RequireFeatures("OrchardCore.Media")] |
Compose the type only when all listed features (from any module) are enabled. |
[RequiredStartup] |
Compose the type for every tenant, even if its feature is disabled; its services belong to Application.DefaultFeatureId. Can be combined with [RequireFeatures]. |
// Composed in every tenant where OrchardCore.Users is enabled,
// whether or not the module's own feature is enabled.
[RequiredStartup]
[RequireFeatures("OrchardCore.Users")]
public sealed class UserCleanupStartup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IUserEventHandler, UserCleanupHandler>();
}
}
Wrong (OCSG002, silently ignored at runtime):
[Feature("OrchardCore.Liquid")] // Not declared by this module.
public sealed class LiquidStartup : StartupBase { }
Right:
[RequireFeatures("OrchardCore.Liquid")]
public sealed class LiquidStartup : StartupBase { }
Project File Pattern
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OrchardCore.Module.Targets" Version="3.*" />
</ItemGroup>
</Project>
Module Folder Structure
MyModule/
├── Manifest.cs
├── Startup.cs
├── MyModule.csproj
├── Controllers/
├── Drivers/
├── Handlers/
├── Migrations/
├── Models/
├── Services/
├── ViewModels/
├── Views/
└── wwwroot/
Files in wwwroot/ are served at /{ModuleId}/... (e.g. /MyModule/js/app.js), from the project folder during development and from the embedded assembly resources otherwise.
Orchard Core 4.0 Authoring Checklist
- Display drivers:
Initialize<T>()/Factory();Shape()is obsolete. - Permissions: static
*Permissionsclass,LocalizationSource.Create(...)descriptions,services.AddPermissionProvider<T>(). - Admin pages:
<breadcrumb>in theTitlezone,<admin-list>for lists,AdminNavigationProviderfor menus. - Admin scripts: no jQuery; editor scripts as
<script at="Foot" type="module">. - Temporary files:
ITempDirectoryProvider; user uploads:FileCreationService. - Options built from site settings:
IOptionsMonitor<T>.CurrentValue.
See orchardcore-module-creator for code templates of each item, and references/module-examples.md for a complete module.