githubEdit

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:

Concept
Purpose
Example

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:

  1. Creates or retrieves a feature instance

  2. Configures the feature (optional)

  3. Registers services and activities

  4. 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:

  1. Naming Convention:

    • Feature: XyzFeature

    • Extension method: UseXyz()

    • Options: XyzOptions

  2. Registration Flow:

  3. Method Chaining:

Complete Module Structure

Here's the recommended structure for a module project:

Best Practices

1. Follow Naming Conventions

  • Use XyzFeature for feature classes

  • Use UseXyz() for extension methods

  • Use XyzOptions for 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

Summary

Creating custom modules in Elsa v3:

  1. Create a Feature - Inherit from FeatureBase

  2. Register Components - Add activities, services, and configuration

  3. Create Extension Method - Follow the UseXyz() pattern

  4. Package & 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