Johan Björnfot
Oct 19, 2012
visibility 9868
star star star star star
(4 votes)

EPiServer7 – Routing

Introduction

In previous versions of EPiServer CMS the Friendly Url (FURL) handling was performed by an IHttpModule that executed early on incoming requests and rewrote the path to the aspx file that was specified by the page type. The module also hooked up a Filter on the outgoing response and parsed the outgoing html and rewrote urls to FURLs.

In CMS 7 the FURL handling has been rewritten to be based on the built-in routing in .NET 4.0. To use routing when using WebForms EPiServer.Web.HierarchicalUrlRewriteProvider must be set as URL rewrite provider on the site and the http module for url rewriting should be EPiServer.Web.RoutingUrlRewriteModule. Any other UrlRewriter (not inheriting HierarchicalUrlRewriteProvider) implementation will not use routing to handle incoming request but instead the previously used UrlRewrite functionality. MVC implementations will not use the UrlRewrite provider. In that case the outgoing urls are constructed using System.Web.Routing.RouteTable directly from views/controllers using for example HtmlHelper extension methods or UrlResolver class.

Default routes

There are several routes registered by default. The Shell modules will have routes registered to support routing to for example edit components and gadgets. The CMS will also register a number of routes by default. The CMS routes are registered in GlobalBase during initialization, it is possible to override method RegisterRoutes in Global.asax.cs to customize the registered routes or add additional routes. The namespace EPiServer.Web.Routing contains some extension methods for the class RouteCollection. Those extension methods can be used to register customized content routes. Among the default routes there will be one set up for routing simple address, one for each site (can be several in enterprise scenarios), and one that routes pages/content from the root (that is pages/content not under any start page). The "ordinary" MVC route "{controller}/{action}" is also registered to support partial request through for example Html.RenderAction, however direct browsing to those routes are prevented. The routes are registered in the order above. This is important because the first route will look if the URL matches its route, and if it does, the page will be routed through that route. If the URL does not match the first route, the next route will get its chance.

MVC and Web Forms

An URL can be routed through the routing framework for both MVC and web forms. The routing will first from the URL locate the content routed to. After the content has been located, the framework will query the EPiServer.Web.TemplateResolver instance which template that should be used to render the request. The template can be either a MVC controller or a WebForm. Then depending on if the template is a WebForm or a MVC controller a suitable httpHandler is set to handle the request. If no content is found that matches the URL or if no template is found that matches the routed content a 404 is returned.

Extending routing

Routing can be extended in several levels. There are events exposed both during incoming routing and creation of outgoing URLs that can be used to customize routing. It is also possible to modify the default URL pattern for content routing to handle part of the URL. And you can also add your own routes.

Events

The class EPiServer.Web.Routing.ContentRoute (that is responsible for routing to content) exposes static events RoutingContent, RoutedContent that are raised during incoming routing. RoutingContent are raised before the default routing implementation is executed and in an event handler can for example the content that should match the request be set. RoutedContent are raised after the default routing has executed and in an event handler can for example the routed content be replaced. During outgoing URL generation are the events CreatingVirtualPath and CreatedVirtualPath raised where event handlers can modify the URLs generated.

Modifying Content routing

The built in content routing is based on that an URL pattern is registered where each pattern is handled by an implementation of an interface EPiServer.Web.Routing.Segments.ISegment. It is possible to implement custom ISegment types and register them as part of the content routing.

By default content routing is registered with a pattern as  "{language}/{node}/{partial}/{action}". The {language} part says that in the url there might first be an optional part that states the language. The {node} part is used to specify the CMS page/content in the URL, it will follow the site structure and contain all page names after the start page on the site, down to the requested page. For example, in the following structure "start > news > firstNews", the URL part handled by {node} part would be "/news/firstNews". If there is something remaining in the URL after the page/content routing any registered EPiServer.Web.Routing.IPartialRouter that matches the type of located page will get a chance to route the remaining of the URL. Then at last any remaining part is checked if it is a valid action for a MVC controller. If the requested action would be "myAction" (MVC), the whole URL would be "http://mySite/news/firstNews/myAction".

The 'MapContentRoute' extension method takes the name of the route, the URL pattern, and default values as arguments. Each part in the URL pattern for content routing (for example {node} or {partial}) is handled by an implementation of EPiServer.Web.Routing.Segments.ISegment.

Below is an example on how to add a route:


using EPiServer.Web.Routing;
namespace EPiServer.Samples.MvcTemplates
{
    public class MvcApplication : EPiServer.Global
    {
        protected override void RegisterRoutes(RouteCollection routes)
        {
            //Call base.RegisterRoutes so default CMS routes are registered
            base.RegisterRoutes(routes);
            
            // Register a route, which will make all url:s with 'shop/' before page names route to the page last in the list of page names
            // For example, http://mySite/shop/News/ListOfNews/FirstNews/ will route to the 'FirstNews' page.             
            RouteTable.Routes.MapContentRoute(name: "customRoute", 
                url: "shop/{node}/{partial}/{action}",                
                defaults: new { action = "index" });
        }



Custom route implementations

It is also possible to add custom System.Web.Routing.Route implementations. The order of the routes are important since the first route that handles a request will prevent that following routes get a chance to route the request. So when registering custom routes it is important to decide whether it should be registered before or after the default routes.

Oct 19, 2012

Comments

Mar 25, 2013 03:53 AM

Thank you for the great post!

I have a question regardign modifying the default URL of EPiServer. Is there anyway to debug the original {node} segment? I tried to copy it and rename then add it in the global.asax but it does not work.

Regards,
Hai

error Please login to comment.
Latest blogs
Parallel Development in Optimizely CMS SaaS: Shifting to a Schema Migration Mindset

  Part 3 of the Parallel Development series. The branch-scoped push script from Part 1 works. Run it on a feature branch where you've touched a...

Vipin Banka | Jul 25, 2026

From AI Agents to AI Workflow with Opal

Introduction In the first article in this series , we talked about AI agents in Optimizely Opal and walked through the process of creating a...

Igor Safonov | Jul 23, 2026

Building Your First Optimizely Opal AI Agent: a Hands-On Walkthrough

Introduction There's a common assumption that building an AI agent is something only engineers or developers can do. It isn't. At the Optimizely AN...

Igor Safonov | Jul 23, 2026

Advanced Task Manager Gets a Big Update

One of the things I keep coming back to with Optimizely's content approval workflow is that it's solid at the individual level - you know a piece o...

Adnan Zameer | Jul 21, 2026 |

Parallel Development in Optimizely CMS SaaS: A Smarter Way to Register Components

📌 A note before you read: The approach described in this article is not a replacement for Optimizely’s recommended out-of-the-box component...

Vipin Banka | Jul 21, 2026

How I Deployed My Optimizely Content JS SDK Next.js App on Vercel (Hello Opti World)

📌 Scope: This post covers Optimizely CMS (SaaS) only, using the official content-js-sdk with Next.js 15 deployed to Vercel. This is a practitioner...

Kiran Patil | Jul 21, 2026 |