Create your own Global Events
Part of what makes any CMS worth its salt is the ability to extend its functionality. Kentico has done this through Global Event hooks, which allow you to intercept and modify the behavior of the internal workings at certain key points. All the Info objects inherit this and have an Insert/Update/Delete
Before/After
event hooks, and on top of that Kentico offers many other custom hook points.
All of these use a couple base Kentico classes that handle the creation and delegation of these events, and since these classes aren’t hidden away, that means we can leverage them as well to make our custom modules easily extensible.
If you are creating a marketplace submission, or even an internal module that you plan on using on multiple sites, global events are probably something you’re going to benefit from.
Flexibility vs. Complexity
The more flexible a tool is, the more places it can be used. However, this usually comes at a big cost, and that cost is complexity. Trying to imagine all the different use cases, the different scenarios, and coding in logic to handle all of those can be a nightmare, and ultimately you can never truly account for EVERY scenario.
However, by adding in some custom event hooks, you can allow individuals who use this tool to modify it just how they need it, in their own unique situations. This is the beauty of the event hook system.
Setting up the Event
Creating a custom event is quite simple:
- Create your
CMSEventArgs
class (event properties)
- Create your
EventHandler
- Create your Event Class
Let’s look at the code for each, I’ll be using the
DynamicRoutingEvents.GetPage
as an example.
Create your CMSEventArgs class
The first step is to decide what you’ll pass to the Events. This can be any class you wish but should contain any data the user may need to perform relative actions. This class must inherit from CMSEventArgs
for Kentico to allow it to be used.
Failed to load widget object.
The file '/CMSWebParts/Custom/HighlightJS/HighlightJS.ascx' does not exist.
Create your EventHandler
The next step is to create your Event Handler class. This needs to inherit the AdvancedHandler<YourEventHandler, YourEventArgs>
class. The only thing worth mentioning on this is since the base Finish
method is hidden, you need to add your own Finish Event to call this, which triggers the After
event.
Failed to load widget object.
The file '/CMSWebParts/Custom/HighlightJS/HighlightJS.ascx' does not exist.
Create your Event Class
The Last step is to create a static class that will expose your handler, making it easy for the user to add their own hooks to it. Just follow the below example’s format.
Failed to load widget object.
The file '/CMSWebParts/Custom/HighlightJS/HighlightJS.ascx' does not exist.
Leveraging the Event in our Code
Now that we created our event, let’s go through using it in our code, using this outline:
- Create your Event Argument
- Initialize the Event (
Before
Event triggered)
- Perform your normal logic (possibly considering if the user used the Before trigger)
- Call the Finished method (
After
Event triggered)
- Finish your logic/method.
We’ll summarize and then go into detail on each step. We will be using the example of my
DynamicRouteHelper.GetPage() method, which leverages the
DynamicRoutingEvents.GetPage
event.
1: Create your Event Argument
The first step is to create and populate your EventArgs class. This will be passed to the Before
event, and will give the user the information they need, and possibly also properties they may need to modify in order to customize.
Failed to load widget object.
The file '/CMSWebParts/Custom/HighlightJS/HighlightJS.ascx' does not exist.
2: Initialize the Event
Next is to Initialize the event itself by creating a new instance of your EventHandler
(using a using
block is probably preferable in this case). The act of creating a new instance automatically will trigger the Before
event, which allows the users to customize.
Failed to load widget object.
The file '/CMSWebParts/Custom/HighlightJS/HighlightJS.ascx' does not exist.
3: Perform your normal logic
At this point, now you must decide what to do. You should account for anything the user may have done in their hook and adjust accordingly. For the GetPage()
method, I do a check to see if the TreeNode
is null or not, if it is not null then the user must have found the page already in their implementation, so I don’t need to do my default logic of trying to find the page myself. But if it is null, then I need to perform my normal logic to try to get the current page based on the UrlSlugs. How you leverage your arguments will be up to you of course, this is just an example:
Failed to load widget object.
The file '/CMSWebParts/Custom/HighlightJS/HighlightJS.ascx' does not exist.
4: Call the After Event
Last step is to call the
EventHandler
’s
Finished
event, which will trigger the
After
event hook. This should allow users another change to modify the results/behavior. The current
EventArgs
are passed again to the
After
event hooks.
Failed to load widget object.
The file '/CMSWebParts/Custom/HighlightJS/HighlightJS.ascx' does not exist.
5: Finish
Now that everything is complete, you can finish your action. In my case, I’m returning the
TreeNode
found (either by my default logic, or the user’s intervention).
Leveraging the Global Event Hooks
Now that your event hooks I created and you have added it to your logic, others can hook into it. Here’s just a sample of what it would look like for someone to modify the GetPage
logic, in this case if the found page is the CMS.Root
page (user hits just the domain), to replace it with the home page.
Failed to load widget object.
The file '/CMSWebParts/Custom/HighlightJS/HighlightJS.ascx' does not exist.
Conclusion
I hope this little guide will be helpful to all those who are working hard to help expand Kentico further. Know I’ve implemented this in both the
DynamicRouting and the
Kentico Authorization modules, and plan on using this further in future tools as well.