HomeDev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunitySubmit a ticketLog In
GitHubNuGetDev CommunitySubmit a ticket


Describes routing in Optimizely Content Management System (CMS).

The Uniform Resource Locator (URL), a web address, is a character string reference to a resource. In most web browsers, the URL is inside an address bar at the top of a web page. URLs carry information from the browser to the server required to enact a desired action.

A content URL in Optimizely Content Management System (CMS) contains information that refers to content, including the language (specified by a 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.

CMS routing is divided into 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 a URL through the routing framework for controllers and Razor Pages. The routing first locates the content routed from the URL. After the content is found, 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, Razor Page, or custom endpoint. Here, it will match any remaining path of the URL that does not match content against the parameters on the matched endpoints. If no endpoint matches the URL, or if no template matches the routed content, a 404 (not found) is returned.

Extend routing

You can extend routing to several levels. There are events exposed during incoming routing and the 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 endpoints.

Access checks

In an ASP.NET Core application, .AddRouting() is typically called before .AddAuthentication(). This means that the user is not authenticated during routing; instead, authorization is performed after authentication, and the user is evaluated against the episerver:read policy at this stage. Extensions like partial routers or events to route events should not perform access checks because the user is not authenticated at that stage.

Request language

The request language (ContentLanguage.PreferredCulture and IContentLanguageAccessor.Language) is not set until routing has completed. This means that, for example, partial routers should not rely on them being set but should instead explicitly pass in language when, for example, loading content through IContentLoader. The routed language is available in a routing context passed into partial routers or routing event handlers.


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 is 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 segments 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 segment as the 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 parameters for a controller:

app.UseEndpoints(endpoints => {