What’s the context of a 404 response in Episerver?

We had a discussion the other day in our web team, both technical and philosophical; what’s the context of a 404 response? Where in the page tree, if anywhere, is the user if she receives a 404 response? What’s the context of something that can’t be found?

It took some thinking. And this, while probably not the only one, is one solution to tackle the problem.

Episerver, to recap one of my previous posts, routes content by (among other things) picking apart the friendly URL (FURL) and matching it to content in the page tree. An Episerver route contains one or more segments that is used to resolve a FURL into a piece of content. A segment associated with a route can be language, page name, simple address, etc. If any of these segments decides that the HTTP request isn’t a match the next route in the route table will be tried instead in order to find a piece of content.

The built-in node-segment is responsible for locating content in the page tree. It does so by picking apart the FURL and moves down the page tree as it matches a parts of the URL to pieces of content. This makes it possible to create context for a URL that possibly might turn out to be a 404 response.

Consider the following URL: http://some-website.com/first-page/second-page/third-page-not-available/fourth-page/fifth-page. Where third-page-not-available does not exist or is the incorrect name.

Episerver will match first-page, second-page, but not third-page-not-available and therefore return a 404 response for that URL. How do we then identify that the previous pages have been matched to content in the page tree, and therefore sets the context for the 404 response?

We do so by adding a custom route at the end of the routing table and associate a custom segment that will store the content located as we move down the page tree. We know that our custom route will only be hit if the other routes were unable to resolve the FURL. This, by ASP.NET convention, is that if a route is matched then no other routes will be tried, leaving our custom route at the end of the route table as a last resort.

Let’s go ahead with some code to get things done. First we need an IInitializableModule to hook up our custom route.

Per the code above we hok ourselves up to the Episerver routes registered events. When the Episerver routes have been registered we add our custom route last in the routing table that will store the context of a request that returns a 404 response.

What’s important to note is that the ContentRoute we’ve added contains default Episerver segments that are executed before our custom segment. Each of these segments will alter the segment context and by its own decide if the route is valid for the current request. Our route has the following segments: {language} / {node} / {partial} / {action} / {StoreLastRoutedContentForPageBeforePageNotFoundFires}. Meaning that we check the HTTP request against the language-segment, node-segment, partial-segment, action-segment and finally our custom StoreLastRoutedContentForPageBeforePageNotFoundFires-segment.


By hitting a breakpoint in the routes registered event and inspecting the route table we can see that our custom route ends up last.

Let’s have a closer look at our custom segment StoreLastRoutedContentForPages.

Let’s walk through the code above. We’re passed the segment context into the RouteDataMatch-method. As explained, the context that is passed into the RouteDataMatch-method has been altered by the previous segments associated with the route, e.g. the node-segment. The node segment will have resolved the FURL (or at least a part of it) to a ContentReference-object, stored in the context.RoutedContentLink property.

This is the piece of content (or reference) we can associate the request context with. Also, the node-segment has already returned false in its RouteDataMatch-method, signalling that the current route, as a whole, is not valid for the request. However, we can store the last piece of content we were able to find and associate with the current HTTP request.

For simplicity (or lack of better idea) we store the content last identified by the node-segment in the Items property bag of the current HTTP request, making it available further down the HTTP request pipeline.

We also signal that we should display a 404 page for the current request, which is what we’ll dive into in the next post.

Thanks for reading!

Recommended Posts
Contact Us

We're not around right now. But you can send us an email and we'll get back to you, asap.

Not readable? Change text. captcha txt

Start typing and press Enter to search