Today I was working on a project that uses EPiServer version 6. As you probably know EPiServer 6 is still using webforms, not MVC. For SEO optimalisation we needed to rewrite incoming URL’s to make them uniform. For example all these URL’s should go to the same page
/en/Some-Interesting-Page
/Some-Interesting-Page
/en/some-interesting-page
For SEO it is important that there is only one valid URL. Other URL’s should throw a statuscode 301 and redirect to the correct url. For this I needed to do some URL rewriting in EPiServer.
Normally you would start catching an incoming request in the Global.asax.cs file in this method:
1 2 3 4 |
protected void Application_BeginRequest(object sender, EventArgs e) { ... } |
Unfortunality EPiServer overrules this method and therefor its never fired. Instead we need to make a event handler by extending EPiServer functionality:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))] public class RequestHandler : IInitializableHttpModule { public void InitializeHttpEvents(HttpApplication application) { application.BeginRequest += application_BeginRequest; } public void Initialize(EPiServer.Framework.Initialization.InitializationEngine context) { DataFactory.Instance.PublishedPage += Instance_PublishedPage; } public void Uninitialize(EPiServer.Framework.Initialization.InitializationEngine context) { DataFactory.Instance.PublishedPage -= Instance_PublishedPage; } public void Preload(string[] parameters) { } void Instance_PublishedPage(object sender, PageEventArgs e) { //implementation } void application_BeginRequest(object sender, EventArgs e) { //implementation } } |
Now we can catch the request in the application_BeginRequest method. What I now want to do is:
- Get the raw URL that makes the request
- This is a SEO friendly url. Convert it to an internal url so we can get the pagereference.
- Get the pagereference from this internal url.
- Convert this internal url back to a user friendly url.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
void application_BeginRequest(object sender, EventArgs e) { //implementation HttpContext context = HttpContext.Current; var rawurl = "http://skyteam.local"+context.Request.RawUrl; var url = new UrlBuilder(rawurl); object pageReference; Global.UrlRewriteProvider.ConvertToInternal(url, out pageReference); if (pageReference != null && pageReference is PageReference) { PageReference pageref = pageReference as PageReference; EPiServer.Global.UrlRewriteProvider.ConvertToExternal(url, pageref, System.Text.UTF8Encoding.UTF8); // url contains now the CORRECT user friendly URL. if (correctUrl.Path != originalUrl.Path) { context.Response.RedirectPermanent(correctUrl.Path + "/" + correctUrl.Query + correctUrl.Fragment); } } } |
Some other code snippets you might like
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public UrlBuilder ConvertToSEOFriendlyURL(UrlBuilder url, PageReference pageReference = null) { // If pageReference is null try to resolve it if ((pageReference == null) && ((pageReference = resolvePageReference(url)) == null)) { // Its not a page return url; } // First make the path lowercase url.Path = url.Path.ToLower(); // Add trailing slash if missing url.Path = url.Path.EndsWith("/") ? url.Path : url.Path + "/"; // Get all available languages var allLanguages = _availableLanguages ?? DataFactory.Instance.GetPage(PageReference.StartPage).PageLanguages.Select(x => x.ToLower()).ToArray(); var perferredCulture = _preferredCulture ?? ContentLanguage.PreferredCulture.Name.ToLower(); // Split URL in parts and remove all empty parts var parts = url.Path.Split('/').Where(x => !string.IsNullOrEmpty(x)).ToArray(); // Add language to URL if missing. Default language is English (Preferred Culture) url.Path = (parts.Any() && allLanguages.Contains(parts[0])) ? url.Path : string.Format("/{0}{1}", perferredCulture, url.Path); return url; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public PageReference resolvePageReference(UrlBuilder url) { object pageReference; var urlInternal = new UrlBuilder(url.Path); try { Global.UrlRewriteProvider.ConvertToInternal(urlInternal, out pageReference); } catch (Exception) { string RawUrl = (HttpContext.Current != null) ? HttpContext.Current.Request.RawUrl : "Unit Test"; Logger.WarnFormat("Invalid URL '{0}' detected while loading: {1}", RawUrl); return null; } return (pageReference as PageReference); } |
More information
- http://world.episerver.com/Forum/Developer-forum/Developer-to-developer/Thread-Container/2010/7/Get-the-PageReference-Object-from-the-friendly-URLstring/
- http://world.episerver.com/Blogs/Yugeen-Klimenko/Dates/2011/6/How-EPiServer-URL-Rewriting-works/
- http://world.episerver.com/Modules/Forum/Pages/Thread.aspx?id=44891
- http://www.frederikvig.com/2009/05/episerver-filter-part-1/
- http://tedgustaf.com/blog/2011/4/episerver-globalization-code-samples/