Single post

How to, actually, configure friendly URLs in Umbraco

tl;dr

You know what I hate? I hate forum posts which start something like:

I’m having real difficulty getting XYZ working. I’ve done [some stuff] but I’m getting [error message].

And then the next post is:

Ah, never mind. I’ve worked it out.

The reason I hate these posts is because they become Google results. There is a reason that I’m reading that forum post, and there is a reason why I did that Google search. These posts do little more than create noise, and it’s frustrating. It’s basically saying “someone else experienced exactly the same issue as you by following exactly the same steps. Oh, you wanted to know how to fix it? Sorry, no.”

So yeah, anyway, hi.

I’ve been doing some work for someone recently in Umbraco. I hadn’t heard of it before, and the learning curve was a little steep, but once I’d got my head around it I have to say that I have, for the most part at least, been really quite impressed with it. It’s basically a CMS built in .Net that you can either install as a standalone site and start hacking away via the back office, or you can install into an ASP.NET MVC4 project in Visual Studio as a NuGet package. The latter option allows you to drop in your own controllers and other business logic. I found that quite handy for implementing site searches and a contact us form that emails the contents to a pre-defined email address. There is also an online library of packages that you can install into your Umbraco site to do various things (like site searches, for example) but these seem to be mostly geared towards the earlier, WebForms-based, versions rather than the shiny new MVC stuff.

What I have learnt from Umbraco, pretty damn quickly, is that you should back up your entire site, including the database, often. About to embark upon a new bit of functionality? Yeah, back that shit up first. A couple of times I did something which ended up frying the whole thing and I had to start again. The first time this happened I hadn’t spent long on it, so re-creating what I’d done wasn’t a big task. The subsequent times I’d already learned my lesson, so had backups I could restore. I should add that it didn’t happen all that often, but there were moments when it did happen where, if I hadn’t made a backup, I’d have lost a whole stack of work.

What I’ve also learnt is that Umbraco appears to be pretty actively developed. That’s a good thing, but it means that the documentation and the stuff you find on various forums isn’t always up to date. This is especially true since the move to MVC appears to be relatively recent. Unfortunately that means that getting certain things done can be hugely frustrating, especially when you add in the problem that my opening gambit discusses. One such issue I’ve had was getting friendly URLs to work on my installation of Umbaco 6.1.6.

Now, I should add that I thought the URL structure created by Umbraco was pretty friendly already. http://www.mysite.com/about-us.aspx seems pretty straight forward to me. Apparently it’s not friendly enough, and it appears to not be uncommon for people to want to pretend that everything is a directory. So http://www.mysite.com/about-us.aspx becomes http://www.mysite.com/about-us/

Fine, whatever.

If you search for “Umbraco friendly URLs” you’ll almost certainly come across this page. It details steps for setting up friendly URLs on IIS6 and 7. The host I’m using claims to be using IIS7, so I followed the instructions on the page. I found that the URLs generated by Umbraco were now friendly. It was nice to see that NiceUrl() paid attention to the settings, so I didn’t have to trawl through all of my templates adjusting them accordingly. The only problem was that when I tried to actually navigate to any of those URLs, I got a 404.

Other people had that problem, too. They solved it themselves (well done you) but they didn’t share the solution (booo).

It seems that the friendly URL stuff in the wiki was only half of the work — I figured I’d need to hook up the URL rewriting stuff too. This is where the fun really begins!

I opened up UrlRewriting.config and started to tinker. I started out by creating a rewrite rule which took a URL and basically stuck “.aspx” on the end of it. It looked a bit like this:

<add name="friendly-urls"
 virtualurl="^~/(.*)"
 destinationurl="~/$1.aspx" />

This works, for what it’s worth. I don’t really know why it works, because it should have resulted in URLs such as http://www.mysite.com/about-us/.aspx. It didn’t, though. I’m not sure why. Also it should have broken every request for other files, like javascript files and images (http://www.mysite.com/images/logo.jpg.aspx). No, this didn’t break because of those problems. This broke because you couldn’t get to /umbraco/ any more. A CMS isn’t particularly useful if you can’t actually get to the back office!

So I thought I’d create another rule to try to preserve the umbraco part of the site:

<add name="keep-umbraco"
 virtualurl="^~/umbraco(.*)"
 destinationurl="^~/umbraco$1" />

This, dear reader, doesn’t work. What you’ve got there is a rewrite infinite loop. /umbraco/login.aspx (for example) redirects to /umbaco/login.aspx, which redirects to /umbraco/login.aspx… Quite why the rewrite filter doesn’t operate once and then piss off and mind its own business I don’t know, but it is what it is. So I figured I needed a single rule which matched everything except umbraco URLs:

<add name="friendly-urls"
 virtualurl="^~/(?!^umbraco$)(.*)"
 destinationurl="~/$1.aspx" />

Nope. Still doesn’t work.

Then, after some more desperate googling, I came across this page. It says:

I’ve got a scenario there i want the site to run with umbracoUseDirectoryUrls set to true and redirect all calls to “foo/bar.aspx” to the directory “/foo/bar/”.

YES! THAT! Here’s the “answer”:

<!-- SEO | Trim .aspx for directory URLs -->
<!-- Note: using UrlRewriting.Net because IIS UrlRewriting doesn't like rules with .aspx in it -->
<add name="SEO | Trim .aspx for directory URLs"
redirect="Application"
redirectMode="Permanent"
virtualUrl="^/(?![0-9]+.aspx)(?!umbraco/)([^\?]*?).aspx$"
rewriteUrlParameter="ExcludeFromClientQueryString"
destinationUrl="/$1"
ignoreCase="true" />

Alas, that doesn’t work. The reason this doesn’t work is because the transformation is back to front. This assumes that your site really is organised as a series of directories, but you want to pretend to the outside world that it’s a bunch of .aspx pages. So an incoming request for http://www.mysite.com/about-us.aspx would be rewritten to http://www.mysite.com/about-us/. While this wasn’t the right answer, it did lead me to the final solution:

<add name="SEO | Trim .aspx for directory URLs"
 virtualUrl="^~/(?![0-9]+/)(?!umbraco/)([^\?]*?)$"
 rewriteUrlParameter="ExcludeFromClientQueryString"
 destinationUrl="~/$1.aspx"
 ignoreCase="true" />

That, dear reader, works…for me, at least! I can now successfully navigate to each page on the site, and I can also access the umbraco back office. And it all looks fluffy and friendly with none of those pesky file extensions getting in the way.

So, to summarise (and because I’ll put a “tl;dr” link at the top of this post), to get friendly URLs working in Umbraco 6.1.6, you need to:

  1. Follow the instructions on this page.
  2. Add the following rule to UrlRewriting.config:
<add name="SEO | Trim .aspx for directory URLs"
 virtualUrl="^~/(?![0-9]+/)(?!umbraco/)([^\?]*?)$"
 rewriteUrlParameter="ExcludeFromClientQueryString"
 destinationUrl="~/$1.aspx"
 ignoreCase="true" />

Good luck!

Edited to add:

It transpires that the above rule, for me at least, only solves part of the problem. The search stopped working on the site, because it had a query string attached to it, and then when I tried several different incantations for the rewrite rule each one failed in one way or another (500 internal server error, 404 when trying to view the site itself, rendering issues with the Umbraco back office etc). After some experimentation, it seems that this is what’s required:

<add name=”SEO | Trim .aspx for directory URLs”
virtualUrl=”^~/(?!umbraco/?|.*\.axd\?.*)([^\?]*)”
rewriteUrlParameter=”IncludeQueryStringForRewrite”
destinationUrl=”~/$1.aspx”
ignoreCase=”true” />

I can’t say with 100% certainty that this is the answer, but I’m fairly confident.

Darren
January 2nd, 2014 at 11:23 am

This works for me using IIS 7 and Umbraco 7 with MVC, Running locally in Visual Studio was always working but when deployed to IIS the friendly/MVC URLs did not work but now they do, thanks.

Julio
June 19th, 2015 at 11:11 am

You have probably realised this by now: UrlRewriting.config can seriously harm your site performace. Use IIS URL Rewrite instead

carl
July 7th, 2015 at 4:37 pm

Interestingly, the site I was working on at the time was the only one that I had trouble with friendly URLs. There were performance issues, but they’ve mostly been resolved now I believe. Thanks for the heads up though. I’ll bear that in mind if I find myself in a similar situation in the future.

admiss
June 30th, 2016 at 10:35 pm

Hi everyone,

Any idea how to rewite a media ile Url?

FROM: http://www.mysite.com/media/1657/uploadedfile.pdf

TO: http://www.mysite.com/uploadedfile.pdf

Thanks!

LEAVE A COMMENT

theme by teslathemes