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 filtering or HTML manipulation on the output response of a page. One way of doing this is by creating a custom action filter attribute and applying it to the controller you want to filter.
If on the other hand, you want to create a filter that works on all pages, you can create an ActionFilter. 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, before I go into the code, 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 issues I encountered when I got this up and running and explain why certain things need to be done in a certain order. In 99% of the time, 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 as if you can create a solution without needing to change the HTML, that will be better!!!!
Next, there are a few issues you'll likely encounter setting this up, so it's probably a good idea to go into these. First, you'll only want to apply a filter to Episerver page requests. The reason for this is that if you start changing the requests on API request etc... the editor will break. Try it yourself and you should see a 'Failed to load resource: net:: ERR_CONTENT_DECODING_FAILED' error, as can be seen below:
If you're recreating a custom filter and the Episerver editor breaks, then this is likely the issue. Next up, is another filtering of requests issue. I'm not 100% sure if this is a .NET or an Epi thing but 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
This error occurs when you try to add a custom filter to block requests or partial page requests. In a normal MVC program, you have pages and child actions, however, in Episerver blocks a partial page can look like normal page requests, but 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. Bearing that in mind, let's get to the code.
A Custom Filter Code
To create a global filter, you will need to use something similar below:
In the code above we implement the IActionFilter. In here, it's best to add your code to the OnActionExecuting. The reason for this is you can get access to the context HtmlTextWriter, e.g. the HTML easier than after it's been created. You can add code in OnActionExecuted but it is likely you'll need to write call back methods, and there's loads of funky stuff around context. Going into the full detail of the issues with OnActionExecuted are outside this article, but just be warned. Next, we need to filter the results out, using filterContext.ActionParameters.KeysContains(currentPage) to make sure we only read Episerver page request and ignore the rest. you also have to make sure the request isn't a child action, e.g. it's not a 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. If you filter you'll 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. So to check for products you can use this
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 that you can create yourself if you prefer to keep code out of your global.ascx (which I recommend). A filter config might look like this:
In your web.config you then register it like this in your global.ascx Application_start:
Episerver Global Filters Takeaway
Global filters can be used with Episerver, but 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 thing which will likely be very custom to your solution. A quick overview, is you need to get the HTML from the response stream, do whatever you need to it and then write it back. Good luck!