Introduction to Subtext Plugins
Plugins allow any developer to extend the functionalities of Subtext without hacking through the code and recompiling the application.
Using a simple to use API you can:
- modify a post (or story or image) before Subtext saves it to the database
- do something after a post (or story or image) has been stored inside the database
- filter or modify comments before they are saved to the database, or also, do something after the comment has been saved
- add text or modify the contents of a post or comment when it is displayed on the blog or when it is syndicated via RSS
And to install it all you need to do is copy a few files on the server and add a configuration entry in the web.config.
How to develop a plugin for Subtext
A plugin for Subtext is just a class that inherits from a particular base class and handles the events that are raised by Subtext.
In addition to the event handler class, a Subtext plugin can also include a web control to handle its own configuration settings.
Let's see how to write a Subtext plugin
0 - Download and install the latest Subtext v2.0
Plugins are a new feature introduced with Subtext 2.0, so, in order to develop one you have to download the latest version of Subtext 2.0, or get the latest code from our SVN repository
At the time of writing the latest build is version number 2.0.0.224
1 - Create a new VS Project
Create a new Visual Studio project and add the following references to two (2) of the core Subtext assemblies:
- Subtext.Extensibility.dll
- Subtext.Framework.dll
2 - Extend PluginBase
If you are familiar with writing HttpHandlers of HttpModules, the same concepts applies to Subtext plugins.
The first thing to do is to create a new class, and make it inherit from PluginBase.
The only method of the base class you have to implement is Init: inside this method you have to start listening for the events you want to handle.
3 - Adding Plugin Informations with Attribute
The next step is adding attributes to specify a guid for the plugin and some details about his name, the copyright, the version number and so on.
To do this you have to decorate the plugin with 2 attributes:
- Identifier("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"): this will be the unique identifier for the life of your plugin, even in following versions
- Description(
- Name: the friendly name of the plugin
- Author: the author of the plugin
- Company: the company that developed the plugin
- Copyright: copyright information
- HomePageUrl: the URL of the website about the plugin, his author or his company
- Version: the version number of the plugin
- Description: a description of what the plugin does
All this information will be showed to the blog owner in the plugin configuration page.
4 - Handling Events
Then you have to write the event handler you declared inside the Init method.
For the purpose of this example let's say you want to add the current time at the end of the post when it is saved, and then write the time the post is displayed on the homepage of the blog.
To do this you have to handle 2 events (for the list of all the events please refer to the API documentation:
- EntryUpdating
- EntryRendering
EntryUpdating:
1: void sta_EntryUpdating(object sender, SubtextEventArgs e)
2: {
3: Entry entry = e.Entry;
4: switch (e.State)
5: {
6: case ObjectState.Create:
7: entry.Body += "<br><hr> <b>QuickStartPlugin</b>: Created at date: "
8: + DateTime.Now.ToShortDateString() + " "
9: + DateTime.Now.ToShortTimeString();
10: break;
11: case ObjectState.Update:
12: entry.Body += "<br><hr> <b>QuickStartPlugin</b>: Updated at date: "
13: + DateTime.Now.ToShortDateString() + " "
14: + DateTime.Now.ToShortTimeString();
15: break;
16: default:
17: break;
18: }
19: }
EntryRendering:
1: void sta_EntryRendering(object sender, SubtextEventArgs e)
2: {
3: Entry entry = e.Entry;
4: entry.Body += "<br><hr> <b>QuickStartPlugin</b>: Rendered at date: "
5: + DateTime.Now.ToShortDateString() + " "
6: + DateTime.Now.ToShortTimeString();
7: }
A few notes on the two samples:
the sender parameter always contains the reference to the UI object that raised the event, and can be used to notify some message back to the user.
The e parameter instead contains all the information what you need to handle the event:
- State: the current state of the object (entry,comment,image) being handled:
- Create
- Update
- Delete
- None
- Runtime
- Entry: the entry being handled
5 - Installing the Plugin
Now that the plugin is ready you have to add install it on the server.
- First you have to copy the dll of your plugin in the \bin folder of Subtext
- Add the plugin definition inside the STPluginConfiguration section of the web.config file:
inside the pluginlist element add:
1: <add name = "QuickStartPlugin"
2: type = "Subtext.Plugins.QuickStart.QuickStartPlugin, Subtext.Plugins.QuickStart">
3: </add>
6 - Enable the Plugin
The last thing you have to do is to enable the plugin for you blog.
- Open your browser and navigate to the admin of your Subtext blog
- Go to the Settings>Plugin page of the admin: here you will see all the plugin that are installed on the server
- For each the Plugins you can see the information provided (the one that have been added with the Description attribute) clicking on the "Details" link
- And you can enable the plugin for your blog just clicking on the "Enable" button
7 - Testing the plugin
Now that everything has been configured and installed it's time to see if the plugin is working the way it is supposed to:
- write a new post and verify that the line with the current time is added
- load the homepage of your blog verify that there the "Rendered at..." line as well
- edit the post and verify that that there is also the "Updated at..." line
What's next?
Plugins can do much more than this: they can have site-wide settings, blog specific settings, and even post specific settings.
We will talk about settings in the next QuickStart article.
Fine prints
This documentation is based on a pre-release software, so while we'll do our best not to change the core plugin API, some things might be different from the officially released version of included in Subtext 2.0