On rare occasions when you work with Episerver, you'll encounter some strange requirement or a scenario where you'll need to add in some custom request filtering or HTML manipulation within a page lifecycle request. One way of doing this is by creating a custom action filter attribute and applying it to the controller you want to filter. I've had to do this recently on a project and I definitely bumped into a few hidden gotchas. In today's guide, I'll share some tips with you so you don't encounter the same issues.
How To Create A Custom Filter
First, I need to start off with a disclaimer. For most page requests, you shouldn't need to alter the HTML Episerver generates for you. My first bit of advice is before you start going down this path, think about improving your architecture or changing the requirements. If you can create a solution that does not require you to change the output response, that will be better!!!! I always feel that when you start doing non-standard things with Episerver, the most valuable advice I can give you is to explain the pros and cons of the approach and explain why certain things need to be done in a certain order. You can then decide if this is a path you want to follow.
In terms of consideration, you'll only want to apply this approach to Episerver page requests. You can only apply filters to page requests and not blocks, or partial page requests. If you do you'll see a 'Filtering Is Not Allowed' exception.
In a normal MVC program, you have pages and child actions, however, in Episerver you have blocks and partial pages. The requests may look like normal page requests, however, under the hood, they are child actions. This is why, when we get to the code we'll need to ensure that any child action request is ignored. This is done using this check, !filterContext.IsChildAction
.
If you try and apply this technique to API controllers, you should see an error:
Failed to load resource: net:: ERR\_CONTENT\_DECODING\_FAILED
As can be seen below:
If you are creating a custom filter and the Episerver editor breaks, this is likely the issue.
A Custom Filter Code
To create a global filter, you will need to add a class similar to the one below in your project:
In the code above we implement IActionFilter
. it's best to add your custom code that will manipulate the response stream within the OnActionExecuting
method. The reason for adding your custom code here is that you can get access to the response via HtmlTextWriter
. You can add code in OnActionExecuted
, however, it is likely you will also need to write a call back method which can be fiddley to get working. Going into the full pros and cons with using OnActionExecuted
are outside this article, however, just be warned it can be painful. Next, we need to filter the context. This is done using filterContext.ActionParameters.KeysContains(currentPage)
. in here we want to create a rule, to make sure we only read Episerver page requests and ignore any other request. This is done by checking the request isn't a child action, e.g. it's not a block or partial page request. After this, you can write your custom code.
Working With Episerver Commerce and Filters
If you are working with Episerver Commerce, you'll have to deal with products and not just pages. In this filter, you will also need to check for pages and products. You can check if the current request is a product, as the action parameter will contain a 'currentContent' key. This is done using this code:
Registering Your Filter
Before Episerver will start using your custom filter you will need to register it. This is normally done within your global.ascx
, or a custom Filter config class. My preference is to use a custom class as it keeps the global.ascx
cleaner. A filter registration class is structured like this:
You then register the class in your global.ascx
➡ Application_start
:
That's it! You can now manipulate the HTML response output! Global filters can be used with Episerver, however, as I'm hoping that I've highlighted here, there are a few things you need to be aware of. I haven't gone into the actual code for manipulating the HTML in this post as there are a ton of articles that explain that and that's the custom code will likely be very custom to your solution. Happy Coding 🤘