kentico

Cancelling out of a global event handler in Kentico CMS

Global Event Handlers in Kentico are a great way to inject your custom functionality into a standard event or process. You can leverage this feature to log an exception into a ticketing system, format an email before it’s sent, or any other type of custom code you need to execute when something else happens.

Kentico provides documentation on implementing these in their user guide. This process is similar between v7 and v8/8.1. What they don’t show in either version is how to stop an action from happening. Let’s take the following example:


Totally real example

You have a number of custom tables in your site that store a User ID for a record. When a user is deleted from the site, these records would then become orphaned and cause some nasty data issues. It would be great to clean these up as you go, or even prevent the deletion all together. Let's start with Version 7:


1. Create a Class Module Loader and hook up the User_Delete_Before event handler.

The first step to registering our custom code is making a new Class Module Loader. In that class, we will register our event handler in the Init() funciton.
 
public override void Init()
{
    UserInfo.TYPEINFO.Events.Delete.Before += Delete_Before;
}


Tip

You can check out Kentico's guide on Global Event Handlers here.


2. Create an event handler to do some awesome custom code to check if the user has records in your custom tables.

After registering our event, this is where we will put our logic to see if they should be deleted.
 
void Delete_Before(object senderObjectEventArgs e)
{
    //Check the user account
    bool blnValid = false;
    int intUserID = ValidationHelper.GetInteger(e.Object["UserID"], 0);
 
    //Check if the user can be deleted
    using (GeneralConnection conn = ConnectionHelper.GetConnection())
    {
        QueryDataParameters param = new QueryDataParameters();
        param.Add("@UserID"intUserID);
        blnValid = ValidationHelper.GetBoolean(conn.ExecuteScalar("[Stored proc to check user]"paramQueryTypeEnum.StoredProceduretrue), false);
    }

}


Tip

You can see I’m getting the UserID from the e.Object collection. This is context-based on the type of event you are handling. All of the CMS_User fields are in that object so it’s a great way to get the info I need.


3. Stop the event if it’s not valid.

In the above code I am checking to see if the user has values in the other tables. If they do, I consider it “not valid” and I will want to stop the process. After some searching and a lot of head scratching, the answer was actually quite easy. I just need to throw an error in the code. Once that occurs, the event handler will stop and the error will be passed up to the function that initiated it.
 
void Delete_Before(object senderObjectEventArgs e)
{
    //Check the user account
    bool blnValid = false;
    int intUserID = ValidationHelper.GetInteger(e.Object["UserID"], 0);
 
    //Check if the user can be deleted
    using (GeneralConnection conn = ConnectionHelper.GetConnection())
    {
        QueryDataParameters param = new QueryDataParameters();
        param.Add("@UserID"intUserID);
        blnValid = ValidationHelper.GetBoolean(conn.ExecuteScalar("[Stored proc to check user]"paramQueryTypeEnum.StoredProceduretrue), false);
    }
 
    if (!blnValid)
    {
        throw new Exception("This user cannot be deleted. Edit the the account to disable access to the site.");
    }
}

There, that is a nice message that we can use to tell the user why they can’t delete that one user they seem to hate.
 

In Version 8 things are little easier. All of the event handling is the same, but cancelling out of it is a bit simpler. All you have to do is call e.Cancel():
 
void Delete_Before(object senderObjectEventArgs e)
{
    //Check the user account
    bool blnValid = false;
    int intUserID = ValidationHelper.GetInteger(e.Object["UserID"], 0);
 
    //Check if the user can be deleted
    using (GeneralConnection conn = ConnectionHelper.GetConnection())
    {
        QueryDataParameters param = new QueryDataParameters();
        param.Add("@UserID"intUserID);
        blnValid = ValidationHelper.GetBoolean(conn.ExecuteScalar("[Stored proc to check user]"paramQueryTypeEnum.StoredProceduretrue), false);
    }
 
    if (!blnValid)
    {
        e.Cancel();
    }
}

This will effectively stop the deletion but it only gives a generic message that the action cancelled. By throwing the error, we can return a customizable message to the user.
 


Summing it up

With both examples you can now gracefully stop the event and return the message to the user. If you were using the above code and tried to delete a user from anywhere in the site the code would execute and prevent the deletion. This a great way to inject your custom logic into a "standard" event and further extend the platform.

Hopefully this helps you in your projects. Now go build something awesome!
Comments
 
comments powered by Disqus

Author

Wiz E. Wig, Mascot & Director of Magic
Wiz E. Wig

Director of Magic

Read more