Mix and Match: Combining Server with Client Routing in Episerver
‘INTERACTIVE’. It’s the buzzword du jour for anyone working in web design. As technology progresses, more websites are functioning like a desktop application instead of a traditional website. ‘Makes sense’, you may argue. But from a technical perspective, there’s still a big difference between these Single Page Applications like Facebook, Cinema Bookings and Ticket Purchases etc compared to regular websites.
As a programmer, your starting point is to decide whether to build a Single Page Application (SPA) or a traditional website. There are a number of different frameworks that make it much easier to build SPAs today compared to a few years back, but it’s also possible to combine an SPA with a traditional website built on top of a CMS.
Given that sites need to deliver an ever-increasing level of user experience, you might have parts or an entire website using a front-end framework to deliver an SPA. Lately, I’ve used client side routing with HTML 5 push state to deliver user friendly navigation routes for two of my clients.
Take for example, a Cinema booking website I worked on last year. When a user visits the site and wants to check the movie time, I could choose to design the page so that the user navigates through a series of filters:
- Choose city
As a traditional website, it would reload each time a user chooses one of those filters. Designed as an SPA, the client is able to manage this without the need to reload the entire page.
However, the result has been unfriendly URLs like
When the page is reloaded by refreshing the page or opening a link, then the server needs to know about all of the URLs that exist in the application. It needs to register what URLs are part of the client application.
Alternatively, imagine if I chose to create a friendly URL such as “site.com/tickets/cinema/show/date/seats” that can be sent to a friend, giving her the exact filter she needs when she loads the page.
What needs to happen in order to achieve this?
You copy the URL for the page you are and send to your friend
The friend opens this link
A request goes to the server
The server figures out: This is part of the single page application so it just loads the single page app to the user browser. This is all done without changing the URL to the browser.
The problem with this kind of approach is that the URL structure that lives in the client application does not match the one that lives on the server. If you are using a traditional hash-based approach, then this works since the Episerver routing does not take the hash part into consideration. But when using HTML5 push state, the Episerver based routing on the server gets confused since you are adding lots of segments that the server is not aware of. This is because Episerver’s structure is based on the content of the website. Sure, you can add custom routes using standard ASP.NET functionality, but things might get a bit tricky if you have a rather complex client application supporting many domain and languages with dynamic segments that are different in each language.
So, how do you combine client and server side routing? Is there another, better way compared to registering custom routes?
The challenge here was to have the server and client routing playing nicely together. Let's first take a look on how the client routing could have looked like:
The start page would be pretty simple on the server side using regular Episerver routing with a start page content type connected to a template. The other pages become a bit trickier though as you need to load the start page view for these as well and then let the client routing direct you to the correct view within the client application. To achieve this, we used the partial routing functionality in Episerver. In this case however, the partial router was not used to load sub content under a page like the case with catalog content in Episerver Commerce, but rather to have everything under a specific page in Episerver in order to load the main page. In other words, this action is similar to an internal redirect to the start page, though the URL remains unchanged since this is needed on the client to route there.
The combined routing for the server and client could be described like this:
Adding the routing in Episerver
Let us take a look on how we achieve this in Episerver. We need to add a partial router. We start by adding a custom route handler in the application start:
In the route config we just register our partial router
Then we add the partial router, where the ‘magic’ actually happens. In this case we made sure to always load the start page whenever underneath we have a URL for a page of the type “SpaPage”. As for the interface IStartPageRouteEndpoint this is just a required interface that is not used for this implementation, since we really do not care about the partial routing.
Combining the routing capabilities of Episerver with a client router like the one in Aurelia is just one option available to programmers. Other front-end frameworks with routers like React or Angular JS could also be used to achieve desired results too. Whatever match works for you, web interactivity remains the ultimate goal.
What are your experiences? Share them below.