Hide menu Last updated: Sep 21 2015

This topic describes routing and URL rewriting in Episerver. 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. Routing rewrites a URL to make it more user-friendly. 

How it works

A rewritten URL, also known as Friendly or Search Engine Friendly (SEF) URL, provides shorter and more relevant-looking links to web pages. By default, the routing system in Episerver uses System.Web.Routing, with specific segments added for language, node, and a partial route. Routing is automatically handled based on content type. The language segment will set the language of the page, and the node segment will set the page reference from the URL. 

The technique adds a degree of separation between the files used to generate a web page and the URL that is presented. The partial route allows you to set the routed data to something else than PageData, for example catalog content in a Commerce solution. The registration of such a partial route is usually done in an initialization module.

Default routes

There are several routes registered by default.

  • Shell modules have routes registered to support routing to gadgets.
  • The CMS also registers a number of routes by default.
    • The CMS routes are registered in GlobalBase during initialization; you can override the RegisterRoutes method in Global.asax.cs to customize the registered routes or add additional routes.
    • The class EPiServer.Global also exposes the RoutesRegistrating and RoutesRegistered events, where you can perform custom registrations.
    • The namespace EPiServer.Web.Routing contains some extension methods for the class RouteCollection. You can use those extension methods to register a route on the site or register a partial router. See Partial routing.
  • Among the default routes there is one set up for each:
    • routing a simple address.
    • routing for sites (can be several sites in a multi-site environment).
    • routing pages/content from the root (that is, pages/content not under any start page).
  • The “ordinary” MVC route “{controller}/{action}” also is registered to support partial requests through Html.RenderAction. However, direct browsing to those routes are prevented.

The routes are registered in the order above. The order is important because the first route checks whether the URL matches its route, and if it does, the page is routed through that route. If the URL does not match the first route, the next route gets its chance.

MVC and Web Forms

You can route a URL through the routing framework for both MVC and Web Forms. 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 either a MVC controller or a Web Form. Depending on if the template is a Web Form 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 (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 also can add your own routes.

Events

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

Modifying ContentRoute

The built-in content routing bases on a URL pattern that is registered, where each pattern is handled by an implementation of an EPiServer.Web.Routing.Segments.ISegment interface. You can implement custom ISegment types and register them as part of the content routing.

By default, content routing is registered with a pattern of {language}/{node}/{partial}/{action}.

  • {language}. In the URL there might be an optional part that states the language.
  • {node}. 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 structure start > news > firstNews, the URL part handled by {node} part would be /news/firstNews.
  • {partial}. 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 gets a chance to route the remaining of the URL.
  • {action}. The remaining part is checked for a valid action for a MVC controller. If the requested action is myAction (MVC), the whole URL is 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. You can extend content routing with own ISegment implementations.

The following example shows how to add a route:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;

using EPiServer.Web.Routing;

namespace CodeSamples
{
    /// <summary>
    /// Code sample class containing cref examples on how to register a route
    /// </summary>
    public static class RegisterCustomRouteExample
    {
        /// <summary>
        /// Register a route which makes 'shop/' in the beginning of the url valid.
        /// This method should only be called when the site starts, for example in 'Application_Start' (Global.asax).
        /// </summary>
        public static void RegisterShopRoute()
        { 
            // 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" },
                contentRootResolver: (s) => s.StartPage);
        }
    }
}

Implementing a custom route

You also can add custom route implementations. The order of the routes are important because the first route handling a request prevents the following routes from routing the request. So when you register custom routes, decide whether it should be registered before or after the default routes.

URL length limitation

ASP.NET has multiple checks that validate the length of the URL and the path in Windows. Under normal circumstances, the default settings are enough, but to support very long URL's, add the following configuration:

<httpRuntime maxUrlLength="1024" relaxedUrlToFileSystemMapping="true"/>

Comments