This section describes how to make your Plugin actually do something. This section contains some general ideas about Plugin development.
Plugin programming pattern
Plugin is based on MVC pattern, where it contains model, view and controller
Plugin Hooks
In order to use Plugin together with the existing application, it requires some way to hook the plugin together with the existing BeYourMarket web application.
Plugin Hooks is based on the concept where a set of callback function is defined and would be called based on certain hooks (via routes). BeYourMarket provide a HookBasePlugin class which already implements standard way to tell how to links the callback with routes. Dependency Injection is also used in order to discover plugins interface and implementation.
Here is an example:
We defined a class GoogleAnalyticsPlugin derived from HookBasePlugin where it would insert a piece script in the header on each page to track website traffic.
Code Block | ||
---|---|---|
| ||
public class GoogleAnalyticsPlugin : HookBasePlugin
{
...
} |
Plugin Routes
Plugin Routes define what callback should be executed on certain hook.
For example, in the code below, it defines action Index on controller GoogleAnalytics shall be called on Hook HookName.Head. The controller action would return a View with a piece of script.
Code Block | ||
---|---|---|
| ||
public class GoogleAnalyticsPlugin : HookBasePlugin
{
public const string SettingTrackingID = "GoogleAnalytics_TrackingID";
private readonly ISettingDictionaryService _settingDictionaryService;
private readonly IUnitOfWorkAsync _unitOfWorkAsync;
public GoogleAnalyticsPlugin(
ISettingDictionaryService settingDictionaryService,
IUnitOfWorkAsync unitOfWorkAsync)
{
_settingDictionaryService = settingDictionaryService;
_unitOfWorkAsync = unitOfWorkAsync;
AddRoute(HookName.Head, new RouteValueDictionary
{
{ "action", "Index" },
{ "controller", "GoogleAnalytics" },
{ "namespaces", "Plugin.Widget.GoogleAnalytics.Controllers"},
{ "area", null},
{ "hookName", HookName.Head}
});
}
...
} |
Plugin Administration
In most cases, the plugin would need to be configured by user with some specific information. For example, in the GoogleAnalytics plugin, user needs to configure the TrackingID in order to generate the script.
In the Admin Panel, there is a Configure button on each plugin, which will then be redirected to a configuration page on that plugin. It can be done by adding the route to the Configuration hook, as below. It would link the action Configure on the controller GoogleAnalytics.
Code Block |
---|
AddRoute(HookName.Configuration, new RouteValueDictionary {
{ "action", "Configure" },
{ "controller", "GoogleAnalytics" },
{ "namespaces", "Plugin.Widget.GoogleAnalytics.Controllers" },
{ "area", null }
}); |
Plugin Install/Uninstall
When a Plugin is installed or uninstalled, you might want to insert/remove some data afterwards. To achieve this, HookBasePlugin provide Install/Uninstall method to be overridden which would be called after installing/uninstalling plugin.
Here is an example, GoogleAnalyticsPlugin insert a google analytics setting after installing and remove it when uninstalling.
Code Block |
---|
/// <summary>
/// Install plugin
/// </summary>
public override void Install()
{
// Add settings
_settingDictionaryService.Insert(new BeYourMarket.Model.Models.SettingDictionary()
{
Name = SettingTrackingID,
Value = string.Empty,
Created = DateTime.Now,
LastUpdated = DateTime.Now,
ObjectState = Repository.Pattern.Infrastructure.ObjectState.Added,
SettingID = CacheHelper.Settings.ID
});
_unitOfWorkAsync.SaveChanges();
base.Install();
}
/// <summary>
/// Uninstall plugin
/// </summary>
public override void Uninstall()
{
// Remove settings
var settings = _settingDictionaryService.Query(x => x.Name == SettingTrackingID).Select();
foreach (var setting in settings)
{
_settingDictionaryService.Delete(setting);
}
_unitOfWorkAsync.SaveChanges();
base.Uninstall();
} |
Saving Plugin Data to the Database
To get/save data to the database from the Plugin, the easiest way is to use ISettingDictionaryService, which can be injected via dependency injection. It could be used to save/get settings to the table Settings.
And in other cases where new tables are required, it would need to define Model and Migrations in order to get the tables created during installation. It would require a few classes and steps to do it. Example for reference is Plugin.Payment.Stripe, which is part of the BeYourMarket solution.