Virtual Happy Hour this month, Jun 28, we'll be getting a sneak preview at our soon to launch SaaS CMS!

Try our conversational search powered by Generative AI!

Area: Optimizely CMS
Applies to versions: 12 and higher
Other versions:
ARCHIVED This content is retired and no longer maintained. See the version selector for other versions of this topic.


Recommended reading 
Note: This documentation is for the preview version of the upcoming release of CMS 12/Commerce 14/Search & Navigation 14. Features included here might not be complete, and might be changed before becoming available in the public release. This documentation is provided for evaluation purposes only.

This topic describes routing in Optimizely CMS. The URL (Uniform Resource Locator), also known as a web address, is a character string reference to a resource. In most web browsers, the URL displays at the top of a web page, inside an address bar. URLs carry information from the browser to the server required to enact a desired action. 

How it works

A content URL in CMS contains information that refers to content, including the language (specified either by host or a language segment). The URL can contain additional segments consumed by partial routes (if registered and matches content) and optional custom registered parameter segments. 

Routing in CMS is divided in a content URL routing part that is not dependent on web context, meaning you can generate and resolve content URLs in a non-web context. There is an addition to the endpoint routing in ASP.NET Core that extends the content URL routing with routing to MVC controllers or Razor Pages, including parameters that are used when there is a web context.


The following endpoints are registered by default.

  • Shell modules have endpoints registered to support routing to module controllers.
  • CMS registers a wildcard endpoint that routes to content and then maps the request to a matching MVC controller or Razor Page.

The “ordinary” MVC routes like “{controller}/{action}” are not registered by default. You can call ASP.NET Core extension methods like MapRazorPages or MapControllerRoute to register "ordinary" MVC endpoints also. 

Controller or Razor Page routing

You can route an URL through the routing framework for both controllers and Razor Pages. The routing first locates the content routed to from the URL. After the content is located, the framework queries the EPiServer.Web.TemplateResolver instance for the template that should be used to render the request. The template can be an MVC controller or a Razor Page or a custom endpoint. Here it will match any remaining path of the url that is not matching content against the parameters on the matched endpoints. If no endpoint is found that matches the URL, or if no template is found that matches the routed content, a 404 (not found) is returned.

Extending routing

You can extend routing in several levels. There are events exposed both during incoming routing and creation of outgoing URLs to customize routing. You also can modify the default URL pattern for content routing to handle a part of the URL. You can also add your own endpoints.


The EPiServer.Core.Routing.IContentUrlResolverEvents interface exposes the events ResolvingUrl and ResolvedUrl, which are raised during incoming routing. ResolvingUrl events are raised before executing the default routing implementation, and the content that matches the request is set in an event handler. ResolvedUrl events are raised after executing the default routing, and the routed content is replaced in an event handler. The EPiServer.Core.Routing.IContentUrlGeneratorEvents interface exposes the events GeneratingUrl and GeneratedUrl that are raised where event handlers can modify the generated URLs.

Partial routing

You can register a partial route that is called during content routing if there is a remaining path after content routing. See Partial routing.

Custom content roots

To register content routing for a custom content root (that is a starting point for content routing) one can implement interface EPiServer.Core.Routing.Pipeline.IContentRouteRegister and register the implementation in the DI container. The implementation can then optionally define static segements that should prepend the content route.

Route parameters

If there is a remaining path after content routing the remaining path is matched against matched endpoints. If there is a single segement as remaining path and that segment matches an action on a matched controller then the request is routed to that action. You can also define routing to action parameters by using method MapTemplate on IContentEndpointRouteBuilder that is returned when extension method MapContent is called on IEndpointRouteBuilder.

The following example shows how to register actions with skip and take parameter for a controller:

app.UseEndpoints(endpoints =>
Do you find this information helpful? Please log in to provide feedback.

Last updated: Jul 02, 2021

Recommended reading