Getting started with modules
Overview
Modules are designed to extend Smartstore functionality in any way you can imagine. There are no limits to what features they can add.
Here are a few examples of what modules can do:
alter the way the app operates
change workflows
modify / extend UI
overwrite services
Modules are sets of extensions that compile into a single assembly in order to be re-used in other Smartstore shops. Even though it may use Smartstore APIs, they are no necessity. The only two requirements for a module project are:
module.json
: A manifest file describing the metadata of a module.Module.cs
: A class that implementsIModule
and contains (un-)installation routines.
Some special, mostly commerce related features are encapsulated as providers in the Smartstore ecosystem. A module can expose as many of these providers as needed.
Represented by their interfaces, provider types are:
IPaymentMethod
: Payment providers (PayPal, Stripe, AmazonPay, offline payment etc.)ITaxProvider
: Tax calculationIShippingRateComputationMethod
: Shipping fee calculationIExportProvider
: Data export (Shops, products, orders etc.)IMediaStorageProvider
: Storage for media file blobsIOutputCacheProvider
: Storage for output cache itemsIWidget
: Content rendering in UIIExternalAuthenticationMethod
: External authenticators (Google, Facebook etc.)IExchangeRateProvider
: Live currency rates
Module structure
A module is a regular Class Library project in the solution. It should be placed in the /src/Smartstore.Modules/ directory in the root of your solution.
Do not confuse this with the /src/Smartstore.Web/Modules/ directory, which is the build target for module. From here the application loads module assemblies into the app-domain dynamically.
If your project directory is located elsewhere, you should create a symlink that links to the actual location.
For module projects we recommend the naming convention {Organization}.{ModuleName}, but you can choose any name you wish. It should also be the root namespace and the module system name.
If your module is called MyOrg.MyGreatModule, the .csproj project file should look like this:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<Product>A great module for Smartstore</Product>
<OutputPath>..\..\Smartstore.Web\Modules\MyOrg.MyGreatModule</OutputPath>
<OutDir>$(OutputPath)</OutDir>
</PropertyGroup>
</Project>
Each time the solution is built, your module will be compiled and copied to the OutputPath
directory specified here.
Smartstore.Module.props
The file Smartstore.Build/Smartstore.Module.props defines shared properties for modules. It is auto-included into every project located in Smartstore.Modules/.
Among other things it specifies files and directories...:
to be copied to the
OutputPath
, if they exist.module.json
wwwroot/
Localization/
Views/
not to be copied to the
OutputPath
.
This is important, because the build process would copy the whole dependency graph to the output, which produces too much noise and file redundancy.
Project & Package references
All projects located in the Smartstore.Modules directory reference Smartstore
, Smartstore.Core
and Smartstore.Web.Common
projects by default.
You can reference any NuGet package you wish, but special consideration is required for packages that are not referenced by the app core (private). These need to be listed under PrivateReferences
in module.json (see below), otherwise a runtime error is thrown.
Manifest: module.json
This file describes your module to the system and is used by the Plugin Manager in it's administration screen.
Here is an example of a working module.json
file.
{
"$schema": "../module.schema.json",
"Author": "MyOrg",
"Group": "Payment",
// Required. Module system name.
"SystemName": "MyOrg.MyGreatModule",
// Required. English friendly name.
"FriendlyName": "A great module for Smartstore",
"Description": "Lorem ipsum",
// Required. The current version of module.
"Version": "5.0",
"MinAppVersion": "5.0",
"Order": 1,
"ResourceRootKey": "Plugins.Payments.MyGreatModule",
"ProjectUrl": "https://myorg.com",
"PrivateReferences": [
"MiniProfiler.Shared",
"MiniProfiler.AspNetCore",
"MiniProfiler.AspNetCore.Mvc",
"MiniProfiler.EntityFrameworkCore"
]
}
The following table explains the schema.
AssemblyName
string
The assembly name. Default: '{SystemName}.dll'
Author
string
The author's name.
FriendlyName *
string
A readable, easy to understand, english name.
Group
enum
A conceptual group name. Used to visually categorize modules in listings.
Possible values: Admin, Marketing, Payment, Shipping, Tax, Analytics, CMS, Media, SEO, Data, Globalization, Api, Mobile, Social, Security, Developer, Sales, Design, Performance, B2B, Storefront, Law.
DependsOn
array
Array of module system names the module depends on.
Description
string
A short english description of the module.
MinAppVersion
string
The minimum compatible application version, e.g. '5.0.2'.
The module will be unavailable, if the current app version is lower than this value.
Order
integer
The display order in the module manager group.
PrivateReferences
array
Optional array of private dependency package names that a module references.
By default referenced packages are not copied to the OutputPath
. It is assumed, that the application core already references them. Any private module package should be listed here, including the complete dependency chain.
ProjectUrl
string
Link to the project's or author's homepage.
SystemName *
string
Module system name. Usually the assembly name without the extension.
Tags
string
Comma-separated tags
Version *
string
The current version of the module e.g. '5.1.0'
Module entry class
Every module needs an entry class containing the bare minimum of the un- and install methods. To be recognized as such the class must implement the IModule
interface.
The installation method IModule.InstallAsync()
is called every time the module is installed. Respectively the same goes for the uninstall method IModule.UninstallAsync()
.
By convention the file named Module.cs
is internal
and is placed in the project's root directory.
The IConfigurable
interface is used to expose the route to a module configuration page linked to the Plugin Manager UI.
The following code shows an example of a working Module.cs
file.
internal class Module : ModuleBase, IConfigurable
{
public RouteInfo GetConfigurationRoute()
=> new("Configure", "MyGreatAdmin", new { area = "Admin" });
public override async Task InstallAsync(ModuleInstallationContext context)
{
// Saves the default state of a settings class to the database
// without overwriting existing values.
await TrySaveSettingsAsync<MyGreatModuleSettings>();
// Imports all language resources for the current module from
// xml files in "Localization" directory (if any found).
await ImportLanguageResourcesAsync();
// VERY IMPORTANT! Don't forget to call.
await base.InstallAsync(context);
}
public override async Task UninstallAsync()
{
// Deletes all "MyGreatModuleSettings" properties settings from the database.
await DeleteSettingsAsync<MyGreatModuleSettings>();
// Deletes all language resource for the current module
// if "ResourceRootKey" is module.json is not empty.
await DeleteLanguageResourcesAsync();
// VERY IMPORTANT! Don't forget to call.
await base.UninstallAsync();
}
}
Files & Folders Best Practices
There are some conventions on how to organize the files and directories within a project. Though there is no obligation to comply, it makes things predictable and easier to maintain.
The following is an exhaustive list of files & folders.
π App_Data
App specific (cargo) data like templates, sample files etc. that needs to be published.
π Blocks
Page Builder Block implementations (see Page Builder and Blocks).
π Bootstrapping
Bootstrapping code like Autofac modules, DI extensions etc.
π Client
RESTful API clients
π Components
MVC View Components (see Controllers and ViewComponents)
π Configuration
Settings class implementations (see Configuration)
π Controllers
MVC Controllers (see Controllers and ViewComponents)
π Domain
Domain entities (see Domain)
π Extensions
Static extension method classes
π Filters
MVC Filters (see Filters)
π Hooks
Hook implementations (see Hooks)
π Localization
Localization files (see Localizing modules)
π Media
Media system related classes
π Migrations
Fluent data migrations (see Database Migrations)
π Models
View model classes (see Data Modelling)
π Providers
Provider implementations
π Security
Security related classes
π Services
Service classes
π Utils
Utilities
π Tasks
Task scheduler jobs (see Scheduling)
π TagHelpers
Tag Helpers
π Views
Razor view/template files
π wwwroot
Static files (including Sass)
ποΈ AdminMenu.cs
Admin menu hook (see Menus)
ποΈ CacheableRoutes.cs
Route registrar for output cache (see Output Cache)
ποΈ Events.cs
Event handler methods (see Events)
ποΈ Module.cs *
Required. Module entry class (implements IModule
).
ποΈ module.json *
Required. Module metadata manifest.
ποΈ Permissions.cs
Module permissions (see Security)
ποΈ Startup.cs
Module bootstrapper (see Bootstrapping)
Last updated
Was this helpful?