Extensibility
Learn how to extend Elsa Workflows v3 with custom modules and plugins. Covers module registration, contributing activities, services, and API endpoints with practical examples.
Elsa Workflows v3 is built on a powerful module and plugin architecture that makes it easy to extend the framework with custom functionality. This guide explains what modules are, how they work, and how to create your own modules that contribute activities, services, and even API endpoints.
What is a Module?
In Elsa v3, a module is a logical unit that groups related functionality together. Think of a module as a plugin that can be "installed" into your Elsa application to add new capabilities.
Key Characteristics of Modules
Self-contained: Each module encapsulates related features
Composable: Modules can be mixed and matched
Configurable: Modules expose configuration options via fluent API
Discoverable: Modules follow a consistent naming and registration pattern
Module vs Feature
Elsa's architecture uses two related concepts:
Module
Container for features, exposed via IModule
The Elsa configuration object
Feature
Self-contained unit of functionality inheriting from FeatureBase
HttpFeature, EmailFeature
In practice, you'll typically create features and register them with the Elsa module using extension methods.
How Modules are Registered
Modules are registered during application startup using the AddElsa() method:
Each UseXyz() method is an extension method that:
Creates or retrieves a feature instance
Configures the feature (optional)
Registers services and activities
Returns the module for method chaining
Module Contributions
Modules can contribute three main types of functionality to Elsa:
1. Activities
Custom activities that workflow designers can use in their workflows.
2. Services
Services registered with dependency injection that activities and other components can consume.
3. API Endpoints
REST API endpoints that extend Elsa Server's capabilities.
Let's explore each of these with practical examples.
Creating a Custom Module
We'll create a complete example module called MyReportingModule that demonstrates all three contribution types.
Step 1: Create the Feature Class
A feature inherits from FeatureBase and defines what gets registered:
Step 2: Create a Custom Activity
Create an activity that uses the registered service:
Step 3: Create the Service Implementation
Implement the service that the activity depends on:
Step 4: Add API Endpoints (Optional)
Expose an API endpoint for accessing generated reports:
To register these endpoints, update your feature:
Then in your Program.cs, after building the app:
Step 5: Create Extension Methods
Create a fluent extension method following Elsa conventions:
Step 6: Use Your Module
Now you can use your custom module in any Elsa application:
The GenerateReport activity is now available in Elsa Studio and can be used in workflows.
Module Configuration Options
For more complex modules, provide configuration options:
Module Discovery Pattern
Modules in Elsa follow a consistent pattern that makes them easy to discover and use:
Naming Convention:
Feature:
XyzFeatureExtension method:
UseXyz()Options:
XyzOptions
Registration Flow:
Method Chaining:
Complete Module Structure
Here's the recommended structure for a module project:
Best Practices
1. Follow Naming Conventions
Use
XyzFeaturefor feature classesUse
UseXyz()for extension methodsUse
XyzOptionsfor configuration classes
2. Minimal Dependencies
Only reference necessary Elsa packages
Keep third-party dependencies minimal
Use interfaces for external dependencies
3. Configuration Over Convention
Provide sensible defaults
Allow configuration via options
Document all configuration properties
4. Documentation
Add XML documentation to all public APIs
Include examples in feature descriptions
Document activity inputs and outputs
5. Testing
Unit test activities independently
Integration test features
Test with different configurations
Packaging as NuGet
To share your module as a NuGet package:
Build and publish:
Real-World Examples
Elsa's built-in features serve as excellent examples:
HTTP Feature
Email Feature
MassTransit Feature
Further Reading
DropIns for independently deployed server-side extension assemblies and packages.
Send email from a workflow for SMTP options, attachments, error handling, and production guidance.
Read CSV data in a workflow for input forms, delimiters, typed mapping, and memory behavior.
GitHub activities for server-side GitHub actions, token handling, GraphQL, and the 3.8.0 watcher limitation.
SQL activities for database client registration, query/command/scalar activities, parameter binding, and result limits.
Kafka activities for consumer/producer definitions, JSON and Avro factories, message matching, and worker lifecycle.
LDAP activities for named directory connections, search and write operations, bind behavior, and Studio boundaries.
Custom Activities - Detailed guide on creating activities
Plugins & Modules - Extended guide with more examples
Architecture Overview - Understanding Elsa's architecture
HTTP Workflows - Example of the HTTP module in action
Summary
Creating custom modules in Elsa v3:
Create a Feature - Inherit from
FeatureBaseRegister Components - Add activities, services, and configuration
Create Extension Method - Follow the
UseXyz()patternPackage & Share - Distribute as NuGet for reuse
With this module architecture, you can extend Elsa to fit any domain or integration scenario while maintaining consistency with the rest of the Elsa ecosystem.
Last updated