Creating custom redirects in Kentico
Whether for products or for user profile pages, sometimes having a single page in the tree display data based on an identifier in the URL is the best way to go. Unfortunately, this means that you can’t use Kentico’s built-in alias paths to handle redirects relating to these pages. I find that also having a central location to manage redirect in the CMS makes things a little easier. It can be used to handle redirects from an old site to the client’s new Kentico site with little fuss.
The setup
First, we need to set up a place to store the redirect rules. In a traditional web application, you might use URL Rewrite in IIS along with a rewrite map. However, this can lead to very large .config files if the client has many pages to redirect. Deploying these can be problematic too, and it can also lead to the site failing to load if the config file gets too big.
I also like to make the redirects accessible to the client via the CMS interface, should they need them.
To that end, we should create a custom table in Kentico.
In addition to the fields that Kentico will add (keep the defaults there) we will add the following fields to our custom table:
FromPath Text(4000)
ToPath Text(4000)
That’s all you will need in terms of setup… now we move to code.
The handler
We are going to use a Kentico Global Event Handler to intercept inbound requests and check for any matches in our custom table.
Create a new method in your project’s Module class…
public static void ActionCustomRedirects(object sender, EventArgs e)
{
if (HttpContext.Current == null)
{
return;
} var request = HttpContext.Current.Request; var item = CustomTableItemProvider.GetItems("CustomTable.CustomRedirects")
.Columns("ToPath")
.Where($"'{SqlHelper.EscapeQuotes(request.RawUrl)}' LIKE FromPath")
.OrderByAscending("ItemOrder")
.TopN(1)
.FirstObject;
if (item != null)
{
URLHelper.RedirectPermanent(item.GetStringValue("ToPath", "/404"), SiteContext.CurrentSiteName);
}
}
Finally, we must wire-up the method above to the Kentico events system. In the OnIntit method of your Module simply add the following:
RequestEvents.Prepare.Execute += HttpHeadersHelper.ActionCustomRedirects;
This ensures that the redirects are checked before anything else happens on each request.
RequestEvents.Prepare.Execute += HttpHeadersHelper.ActionCustomRedirects;
In summary
This method of redirecting requests will be triggered at the start of each request and uses a reverse “LIKE” query so that we can use % wildcards in our “FromPath” entries.
Now in our custom table, we could create a FromPath of “/categories/%/123” and have this map to the ToPath of “/product/123”.
Since we order by ItemOrder and take the first match it allows us to have multiple redirects that get more specific the further down the order list they go.
Overall this method performs very well. Although it does add an extra SQL query to every request, in most cases it has a minimal impact on performance. If performance becomes an issue, you could further restrict it by checking the request URL and not doing redirects for certain types of requests (i.e. images and other static files).
Taking it further
This solution is pretty bare-bones in its basic form, and there could be many optimisations or extensions that could be made to improve or add functionality.
For example, you might add another column to determine the type of redirect to be performed. In this way, you could do a 301, a 302 or even perform some internal rewriting instead of a redirect.
If you have any other ideas on how to extend this or improve it further, let me know in the comments below.