In this tutorial, you will learn how routing works within an Episerver CMS powered website. Routing works differently in an ASP.NET CMS system compared to vanilla MVC ASP.NET. The reason for this is due to CMS content. In a vanilla MVC website, a URL maps to a controller and an action so the routing is simple. This is not how CMS routing works. In Episerver, a URL maps to a virtual page stored in a database. This is why all .NET CMS vendors need to change how the default .NET routing works in order for page requests to map to the correct controller. This difference tends to be a big source of frustration for people new to Episerver. They expect things to work the same as a vanilla website 😞

MVC Routing Vs Episerver Routing

The first thing you should know about Episerver routing is the difference between the default MVC routing rule and a default Episerver routing rule. A normal MVC route can be seen below:

This rule is telling ASP.NET to match any URL, it defines two default values. A controller called home and an action method called index. If a request to www.website.com/ was made this is the controller that would load. If a segment was specified it would use that and default to action inside of that controller called index, e.g. www.website.com/landing would map to a controller called landing and an action called index.

Episerver uses a different default routing rule. When we use Episerver and Url's, the URL look-up is all done within Episerver itself. There is no direct correlation between a controller and the page we want to access in the page tree. For this reason, Episerver does some behind the scenes magic and replaces the concept of {controller} in its routing rule with {node}. this is why you need to use the special Epsierver base class PageControleller when building controllers. It has logic that allows the default Episerver routing rule to work.

Most Episerver routing issues do not happen because of reading pages, they come from posting back to pages. In an Episerver website, if you want to build a form that posts back to a controller you can, however, the custom routing rule will be different. As seen, Episerver does not support controller/action method routing rules like a normal MVC site. This can be really confusing at first as you might expect something to work one way and it doesn't. Instead, an Episerver route rule might look like this:

So to break the ``MapRoute` parameters down:

Name: myRoute is the name I randomly picked for this rule. This can be anything you want it to be. It's the name we register in MVC that no one will ever see. Like normal MVC, it just needs to be unique

URL: This part is very different in Episerver. A URL is broken into segments. Each segment within the URL is used to map to something in Episerver. The basic Episerver rule uses three segments (it also uses a partial segment but its not important here):

{language}/{node}/{action}

Each segment in a URL map is mapped in sequential order of the parameters in the rule. The following Url:

www.website.com/search

Would translate into:

  • {language} = en

  • {node} = 12. You might wonder why 12? 12s is the Episerver page id that maps to the search page in the CMS! This is the magic that maps requests to a controller and an action. This happens before the rendering pipeline gets to the controller. There are a few ways this happens. In the IContentLoader there is a lookup by segment method!

  • {action} = Index.

The default Epsiever PageController defines a default action index so we can make action optional in the Url. Episerver has a few other special segments (read about them here), you will not need to use them unless you want to do partial routing!

defaults: This value maps any default values that should be applied in case it's omitted from the Url.

Based on the Episerver rule, you could create a custom Episerver routing rule like this:

It would call type something like this into a browser www.website.com/tags/tag it would match on this rule and then call a controller. Assuming the controller was created like this:

The routing would work!

Episerver Context

When using Episerver it is still possible to do normal MVC routing on a normal vanilla MVC controller. When you register your routes you have two options. One is the standard MVC MapRoute, the other is to use the Episerver extension MapContentRoute. The issue you will encounter when doing normal MVC routing within a vanilla MVC controller is that you lose access to the Episerver context. When the vanilla controller is executed, the current page object will not be populated and will only return null. This one stumped me for ages.. the breakpoint in my controller got hit but all my Episerver data was null. If you're in this situation, the easiest way to get access to any Episerver data to call it manually using the snippet below:

If you wanted to use a normal MVC page controller and you do not need to access Episerver data, using plain old fashioned MVC routing is the way to go!

Episerver Routing

You may be wondering where should you define your custom Episerver routing rules? In normal vanilla MVC site, you would access the routing table from global.asax and create the rules there. In Episerver it is recommended to define rules within an InitializableModule. Below is a quick code example of how you can create an InitializableModule and define a custom rule:

When you use EPiServer routing, you do not use routes MapRoute anymore, instead, you use MapContentRoute and MapPageRoute. When you use MapPageRoute the Episerver specific segments will get populated correctly. . For reference, these segments all inherit fromEPiServer.Web.Routing.Segments.ISegment`. This should provide you with a basic introduction to how you can get routes up and running. If you've made it this far good luck 😄 . Happy Coding 🤘