Let's solve both these problems with a new ASP.NET feature just pre-released today in alpha form on NuGet. My peer Damian Edwards and developer Levi Broderick along with QA by Pranav and Anton have come up with a pretty awesome solution based on the original "Smarty Routes" idea from Eilon Lipton and the result is FriendlyUrls.

It's also worth noting that this FriendlyUrls NuGet package includes BOTH an ASP.NET 4.5 and ASP.NET 4 version so .NET 4 folks get love too.

FriendlyUrls Hello World Example

First, the obvious example. Bring up Visual Studio and File | New Project | New ASP.NET Web Forms Application. Now, from the Package Manager Console or from Manage NuGet Packages, install Microsoft.AspNet.FriendlyUrls. You'll need to "Include Prerelease" packages with -pre from the command line or via the dropdown in the UI.

Be sure to read the readme.txt that pops up as you'll need to ensure that the FriendlyUrls routing gets called on application startup! I added this one line to my Application_Start:

RouteConfig.RegisterRoutes(RouteTable.Routes);

Here's the cool part. If I hit one of my existing links, like Contact.aspx, look what happened. See how the GET request for /Contact.aspx turned into a 301 redirect to /Contact?

If you have a Web Form called /Foo.aspx, you automatically get a /Foo route and can call your page like that! Hence, Microsoft.AspNet.FriendlyUrls.

Just by adding the one package and calling

routes.EnableFriendlyUrls();

in RouteConfig (this default came down with the NuGet package) my whole WebForms app loses its .ASPX extensions and gets reasonable defaults.

FriendlyUrls Advanced Sample

Get it? Ok, let's dig into some of the obvious next questions and some more advanced scenarios. How do I get values out of the URL? I'm used to Request.QueryString and Request.Form, but how do I get ahold of these URL segments?

Here's a Foo.aspx that I've visited via /Foo.

If I click "Click Me" the URL points to /Foo/bar/34.

NOTE: Be aware of the magic. It makes sense. If there was a 34.aspx in a folder called Bar in a folder called Foo, we would have used that file. There wasn't. If there was a file called Bar.aspx in a folder called Foo we would have used that. There wasn't. So, we used Foo.aspx and passed in the rest of the URL.

UPDATE: One thing I forgot to mention was how to get the values out of the FriendlyURL. You can use things like [Form] and [QueryString] to model bind in WebForms. Now you can add [FriendlyUrlSegments] to get data out, like the ID in this example:

By default FriendlyUrls uses a class called WebFormsFriendlyUrlResolver but you can derive from this class and change its behavior however you like. Here's an example of a "DeviceSpecificWebFormsFriendlyUrlResolver" or, better yet, Mobile Friendly Urls for WebForms.

This derived URL resolver does just that, it resolves URLs to physical Web Forms pages. You'd then pass it into the overload of EnableFriendlyUrls(...);

IMPORTANT NOTE: This code is just a very early sample, there will be a more complete one released later.

Now we've created a map of device specific suffixes, so we can have not Foo.Mobile.aspx, but rather Foo.iPhone.aspx and Foo.OperaMobile.aspx, etc.

Here's a little demo that loads a bunch of names into a list. Here's /async, the desktop view.

Now we'll add jQuery mobile to the mobile master page, and use it on the mobile version of the same page. We're still calling the same data source and reusing all that code.

I'm pretty jazzed about what this means for ASP.NET and Web Forms developers. We're going to continue to push forward and improve ASP.NET even now, after Visual Studio 2012 has been released. Sometimes we'll add small features via NuGet packages, sometimes editor improvements as free VSIX Extensions like the Web Essentials playground for 2012 and larger changes via released updates to all of ASP.NET. I hope you like the direction we're heading.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

Wow thats super cool :) Much awaited feature :) Thanks a lot for keeping a compatibility with 4.0. It will be really helpful for us. Thanks to Damian and Pranav! Definitely needed the feature in ASP.NET Webforms. Guys, you seriously rock \m/

This is all great,awesome really.It may be helpful to see (or try) the implications of the magic behind physical files vs parameters, but I bet most applications have these sorts of magic hanging non-measured (and not having notable performance cost) anyway.

However, this was generally fine with the routes support that already exists now. sure it's easier and it's hence welcome and everything, but the one really wanted feature in ASP.NET web forms I'd guess is: Multiple forms! I know it's probably very difficult to implement with the current webforms architecture though, and wouldn't be as helpful for existing projects, but for new projects, that would be the only reason I'd "happily" create a new webforms project.

This looks great, but my biggest problem with friendly URLs and Web Forms is that the Application_Error method in your Global.asax is not hit if you drop the ".aspx" extension and throw an error on that page. Any chance this works around that issue?

Every tool/feature with 'magic' needs to have a 'show me the magic' mode built in where it will dump why it did/chose something to the debug console for troubleshooting. I don't want to have to throw in random route troubleshooting tools, they should be built in!

Nice work on the urls, keep it up - looking forward to when it will be easy to configure at runtime.

Jed

Monday, September 10, 2012 5:16:31 PM UTC

Thats pretty awesome. It solves a problem I was going to have very shortly!

I believe it was you who once quoted you as saying, "The less you do, the more of it you can do." So please help us do less by posting nuget commands as text instead of images that can't be cut/pasted! :P

Anyway, it looks like FriendlyUrls may make up for the lost keystrokes - thanks!

Pastey

Tuesday, September 11, 2012 11:10:04 PM UTC

Pastey - Did you notice that the NuGet string *is* in the ALT text? ;)

This is great. My only question is - is there a definitive list of all Microsoft supported NuGet packages somewhere, as the list is getting quite large. And perhaps more importantly the status of those packages etc.

FriendlyUrl results in a conflict when there is a folder with the same name as the aspx page without the extension. What is your plan on handling that? Right now it gives priority for the folder name on a development computer.

Mike, I suspect you could use 51Degrees.mobi to enhance the base information provided to .NET so that Android, and all other mobile platforms are better supported. Also the IsMobileExtension override in the example code looks like it could be upgraded to check for other properties such as tablets. James

How could I redirect to a completely different site if the Display Mode is NOT a Phone or a Tablet?

Jim Langdon

Friday, December 07, 2012 3:37:45 PM UTC

To make it work you need to add:using System.Web.Routing;into global.asax as well not onlyRouteConfig.RegisterRoutes(RouteTable.Routes);

great article!

gregorio

Tuesday, January 15, 2013 4:48:25 PM UTC

Hello,I'd like to use this package but I get the following error:"The name 'RouteConfig' does not exist in the current context".I just added:using System.Web.Routing;...protected void Application_Start(object sender, EventArgs e){ RouteConfig.RegisterRoutes(RouteTable.Routes);}Could you help me please?

César

Tuesday, January 15, 2013 7:51:46 PM UTC

Same error here with an empty website...

Jeff

Thursday, January 24, 2013 3:03:54 PM UTC

Nice stuff!! Group can you help me to get it working?I'm using VS 2012 (VB.NET). I have 2 questions:1. When I call Routes.enablefriendlyurls as indicated in this article, I get the following error: Routes.enablefriendlyurls is not a member of System.Web.Routing.RouteCollection. Why?

2. Take the following example:How can I rewrite the url Index.aspx?articleid=123456&languageid=EN as"Index/123456/EN"Does someone have a working example in VB or C#?You can mail it to mobileboy36@gmail.com

Thank you group!

Best regards.

Mobileboy

Friday, January 25, 2013 5:11:01 PM UTC

I'm getting the same issue as reported by Cesar and Jeff.

Clean asp.net Webforms 4.5 project. "The name 'RouteConfig' does not exist in the current context".

The "page.aspx" is called two times... (not post back) it´s two different requests by differents threads.

2# if my page have images with status 404 (not found images) and if i´m calling this page with parameters, i have N different requests o my page, where N = Number of images with 404 status.

could someone help-me?

Rafael

Wednesday, February 06, 2013 3:49:23 AM UTC

The ViewSwitcher is in C# and my project is VB, it seems like the C# code is not compiling. Microsoft.Web.Infrastructure seems to be required but is not loaded as a dependency.

Is there a more complete example for using the ViewSwitcher, I am using the standard Site.Master from Visual Studio 2012 and the Site.Mobile.Master does not look anything like it, it looks like something from Visual Studio 2008 or 2010.

I'm trying this new FriendlyUrls feature but for some reason I don't get that 301 redirect when I access the page with the ".aspx" extension. If I remove it manually everything works as expected.

Any idea why?

Paulo

Wednesday, February 20, 2013 7:21:56 PM UTC

Question: Can we remove the site.mobile.master with no adverse effects? Or is there a way to programatically not call this masterpage when a user hits the site on a mobile device?I really only want the simplified way of having friendly urls. We're designing a website using media quieries so the mobile view will be delivered based on that. Yes, we can split the responsive media queries into seperate css files to work with the mobile master...but it's not exactly clean since we'll now have 2 master pages to update (ie if menu needs updating)

Rui

Thursday, February 21, 2013 7:02:23 PM UTC

@Rui - Yes, it's safe to delete. If it's not there, we won't use it :)

Damian Edwards

Thursday, February 21, 2013 7:03:46 PM UTC

@Paulo - The auto-redirect was turned off for RTW as it can cause issues with some 3rd party handlers. You can turn it on again by passing a FriendlyUrlSettings object to the EnableFriendlyUrls method with the RedirectMode property set to an appropriate value.

Damian Edwards

Saturday, February 23, 2013 3:54:45 AM UTC

Really great! Thank you so much for share it.

Joel

Tuesday, February 26, 2013 4:25:58 PM UTC

Damian, thanks! :)

Paulo

Tuesday, February 26, 2013 9:20:27 PM UTC

I am lost, please help. I installed FriendlyURL from NuGet, ported the .cs code to .vb, added the DeviceSpecificWebFormsFriendlyUrlResolver class, added routes.EnableFriendlyUrls() to global.aspx.Nothing in the resolver class is called and nothing .mobile ever gets called. I am using Visual Studio 2012 and VB. I did not notice any changes in web.config, yet the file get refreshed in the IDE, could that be the issue?

4. Add the following call in your Application Start of Global.asax:RouteConfig.RegisterRoutes(RouteTable.Routes)

Note: If your getting the error "RouteConfig" is not found you didn't install both friendly url packages above.

Tech Note: The Friendly Url Core Package will install a New Start Folder that contains classes and methods to support friendly urls. In VS 2010 look for the App_Start folder under the App_Core folder.That's it, I hope this helps. These instructions are for the ASP.NET Friendly URLs v1.0.0. Not the Pre-Release.

Mike - Giving Back after taking so much. :)

Mike

Saturday, March 09, 2013 5:24:33 AM UTC

Hi

Does anyone know how to use PageMethods with this AspNetFriendlyUrl's enabled?

ThanksAdlie

Adlie

Sunday, March 17, 2013 3:17:46 PM UTC

Does the FriendlyURL package work with web site projects?Or any web application projects?

Namespace ASP Public Module RouteConfig Public Sub RegisterRoutes(routes As RouteCollection) routes.EnableFriendlyUrls() End Sub

End ModuleEnd Namespace

Nathan

Monday, May 13, 2013 8:09:52 PM UTC

I've said before how surprised I am that more ASP.NET Web Forms developers don't use Routing to make their URLs prettier.

Guys, here is the big secret: the customers do not care how your site's URLs look. The only URLs a user types into the browser are filenameless home page URLs that use default pages. The rest are only used in links. Users care about as much about how URLs look as they care about the style of a web site's source code.

The big value of URL rewriting is for mobile views to more easily support mobile devices. If you are using URL rewriting just to make your URLs prettier, you are wasting your time.

Claudio

Friday, May 17, 2013 4:54:50 PM UTC

Hi Scott,This is a nice ASP.NET UrlRouting tool I have ever tried nowadays. I devepoed a asp.net web form app using this tool. Its great working my local IIS. If I deploy to my web hosting, its giving an error about SecurityPermission.Please help me! Thanks a lot.

Yalcin,I am having the same issue with GoDaddy. The odd thing is it was working when I had basic hosting, when I upgraded to Deluxe Hosting it stopped working. Deluxe hosting also came with ASP.NET 4.5 instead of 4.0 so that might have something to do with it. GoDaddy's solution was to disable global.asax on my account (not useful).

I know GoDaddy does not support "FullTrust" on shared accounts but that would not explain why it works on Basic Hosting.

Firstly, I would like to congratulate and thank you for coming up with such an exciting feature with Microsoft ASP.NET. Personally, I liked the option of switching between the Mobile view and desktop view. Awesome!!

I have some troubles using Friendly Urls and static ressources like .js or .css files.

It is the same as described here:http://forums.asp.net/t/873722.aspx/1?Locating+Javascript+file+using+Friendly+URLs

it happens that if you use FriendlyUrl.Href("~/Details", "param") and have the URL "/Details/param?key=value" that all the files used in script tags like src="js/details.js" the request is sent to the page with the request URL "Details/js/details.js" instead of "js/details.js"

If you don't use any parameter after the page name it works fine. Is there any solution without rewriting all references in the project?

Manfred

Thursday, July 11, 2013 11:13:20 PM UTC

Manfred: Because you're passing a parameter to the Href() API, it's adding it as an extra segment to the URL. So you end up requesting the ~/Details.aspx page as “foo.com/Details/param”

Any relative paths in that page will now be treated as relative to ~/Details, as you’d expect.

To fix it, as always, scripts and other resources should not be referenced statically, but rather resolved from app relative root, e.g. ResolveUrl("~/js/details.js")

but Request.GetFriendlyUrlSegments() returns nothing in Directory.aspx. How can I get the parameter passed?

Vikram

Saturday, August 10, 2013 8:30:20 PM UTC

When are these guys going to release the source code?

Fallon

Monday, August 12, 2013 3:27:30 PM UTC

Hi This is awesome plugin for URL friendly rewrite.I Just found on Google and i was trying to on my project but it is not working for me.it giving me errors are below :1. "Could not load type 'ASP.Site_Mobile' "2. "Could not load type 'ASP.ViewSwicther' "

But there's a thing i dont know how it works.How can i get querystring mapped values?I know its possible via foreach ...segmentsBut, is there any way for getting a value like in Request.QueryString["id"] ?

Thanks in advance.

marianux

Monday, October 14, 2013 10:51:04 AM UTC

I'm looking at implementing URL Routing on an ASP.NET Web Forms website. I've been looking at the best way to handle 404 errors so for example:

@Adlie Hendricks, @OmerI just saw your questions last night, I was also facing same problem with FriendlyURLs. I know its too late but I have found a solution by my self.Use direct call to a C# function from ajax, here is a post, it will help you how to call a C# function from ajax.

Although, I would favor a message stating the news article does not exists when no records are returned from a database, on the news article page and use the 404 response for a more catch all type scenario.... It all depends on how your content is driven.

Hope this helps.

Danny

Sunday, October 20, 2013 8:39:31 PM UTC

Jeremy - your response status code can be set to 404 on page load. In fiddler for no records I see the response code as 404 if (dT.Rows.Count == 0) { //send email to dl web development about link expiration. litCmsContent.Text = helpers.notFoundText(); Response.StatusCode = 404; Response.Status = "404 Not Found";}

Danny

Monday, October 21, 2013 2:33:41 PM UTC

Hello, I'm having trouble getting this to work with the selected item of the asp.net Menu control.My sitemap contains urls with the .aspx extension. I don't want to change this because then the option securityTrimmingEnabled="true" of my sitemap provider won't work as expected.Could you point me in the right direction in order to fix this?

Willem

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.