Making URL rewriting on IIS 7 work like IIS 6

Upgrading to IIS 7 should be rather transparent, unfortunately that is not the case when it comes to URL rewriting as we knew it from IIS 6. In IIS 6 all we had to do was to add a wildcard mapping making sure that all requests went through the ASPNET ISAPI process. After this was done, one could create a global.asax file that would either pass requests directly through or rewrite the URL based on an internal algorithm.

UPDATE: Please see my updated post on how to do proper URL rewriting using IIS 7.

I didn't really expect this to be a problem when I first requested http://localhost for the first time after setting up my site on IIS 7 (all default settings).

Image: iis7ur1
Unfortunately this was what I was presented with. Anyone having worked with wildcard mappings from IIS 6 will recognize this, this is the result you'll get after adding a wildcard mapping without having created your URL rewriting functionality. After adding a wildcard map the IIS will not automatically find a default file (by design).

This however, is not the problem cause here. I already have my URL rewriting functionality written in my global.asax BeginRequest method and I'd really like to just reuse my current code. Although the new IIS has a whole new bunch of features - one of them being a new "more correct" way of doing URL rewriting -, I really just wan't to get my website up and running again so I can continue my work.

What I present below is a quick'n'dirty hack that will get my old URL rewriting code to work again. It may not be the IIS 7 way of doing it, and it may not work in your case, it depends on the type of URL mapping you're doing in your project. In short, YMMV.

My scenario
For this website, improve.dk, all URL's except static files are requested as though they were folders. That means you will not see any pages ending in anything but a /. Any static files are requested as usual. That means I can be sure that a regular expression like *.* will catch all static files, while * will catch all pages - as well as the static files!

How I got URL rewriting to work like IIS 6
Start by opening the IIS Manager and selecting your website.

Image: iis7ur2
Now enter the "Handler Mappings" section:

Image: iis7ur3
Notice the "StaticFile" handler. Currently it's set to match * and catch both File and Directory requests. If you look back at the first image, you'll notice that the error message details that the handler causing the 404 error is the StaticFile handler. As I know that all my static files will have a file extension (also I don't care for directory browsing), I'll simply change my StaticFile handler so it only matches *.* - and only files.

Image: iis7ur4

Image: iis7ur5
Your StaticFile handler should now look like this:

Image: iis7ur6
Now, if you go back and make a request to http://localhost you'll still get the 404 error, but this time the request is not handled by the StaticFile handler, actually it doesn't get handled by any handler at all:

Image: iis7ur7
What needs to be done now is that we need to map any and all requests to the aspnet_isapi.dll isapi file - just like we would usually do in IIS 6.

Add a new Script Map to the list of Handler Mappings and set it up like this:

Image: iis7ur8

Image: iis7ur9
Click OK and click Yes at the confirmation dialog:

Image: iis7ur10
Now if you make a request to either http://localhost or any other file you'll get the following error:

Image: iis7ur11
Looking throug the Event log reveals the cause of the error:

Image: iis7ur12
The aspnet_isapi.dll file cannot be used as a Handler for websites running in the new IIS 7 Integrated Mode, thus we will need to make our website run in classic .NET mode. Right click your website node in the IIS Manager and select Advanced Settings. Select the "Classic .NET AppPool" and close the dialog boxes:

Image: iis7ur13
Now you should be able to make a request to http://localhost and see it work. Your URL rewriting should work as a charm aswell:

Image: iis7ur14
But obviously somethings wrong. Making a request to any static file will reveal the problem:

Image: iis7ur15
"Failed to Execute URL", what a great descriptive error. Fortunately you won't have to spend hours ripping out hair... As I have already done that - at least I'll save a trip or two to the barber.

The problem is that the static files are being processed by the aspnet_isapi.dll file instead of simply sending the request along to the StaticFile handler. If you click the "View Ordered List..." link in the IIS Manager from the Handler Mappings view, you'll see the order in which the handlers are being executed for each request:

Image: iis7ur16
When you add a new Script Map it'll automatically get placed at the very top of the line taking precedence over any other handlers, including the StaticFile one.

What we have to do is to move our Wildcard handler to the very bottom, below the StaticFile handler. By letting the StaticFile handler have precedence over our Wildcard handler we ensure that any static files (matching *.*) gets processed correctly while any other URL's gets passed along to our own Wildcard handler that'll do the URL rewriting and make business work as usual:

Image: iis7ur17
After doing so, both static files as well as your custom URL's should execute as they would under IIS 6:

Image: iis7ur18
Disclaimer
Please notice that this is a hack. This is not the way URL rewriting is supposed to be done under IIS 7. But instead of spending hours upon hours investigating how to do it the right way, this is quick fix to make things work like they did before.

Also please note that this solution is intended to work for my specific situation. Your needs for URL rewriting may not necessarily match mine, so you may have to modify certain settings to suit your specific needs.

kick it on DotNetKicks.com


Comments

Bryan Peters | Dec 12th, 2006, 6:26 AM

Excellent writeup and screenshots! I went through the same frustration a few weeks back and fumbled my way through the steps you outlined. I hope the next person finds this helpful - I know I did.

Derek Hatchard | Dec 12th, 2006, 3:13 PM

In Integrated Mode you can write .NET code to hook into the request lifecycle events for any request. No need for an explicit wildcard mapping to aspnet_isapi. Then you can put your URL rewriting logic in a BeginRequest event handler in an HTTP Module (implement IHttpModule).

Mark S. Rasmussen | Dec 12th, 2006, 4:22 PM

Derek,

I'll have to look into the correct way of URL rewriting for sure. But I suppose that the IHttpModule way of doing it is only going to work for IIS7 using Integrated Mode?

I'm still pondering as to how we're supposed to develop our applications on IIS7 while deploying to IIS6 hosts. As I'm running Vista I'll have to use IIS7, but my production environment is running IIS6, so currently I'll probably have to live with a hack like this, until IIS7 can be installed on Server 2003.

Kimsea | Jan 11th, 2007, 5:46 AM

Do you can write sample code Making URL rewriting on IIS 7 work like IIS 6 and posted. Thank you

Sergey P. | Jan 14th, 2007, 10:19 AM

I'm using urlrewriting.net, it's very useful when you haven't access to IIS. What do you think guys, about this component?

dts | Feb 6th, 2007, 5:42 PM

I want to uninstall IIS7 and install IIS6. What are the things I need to care about?

Aaron | Feb 13th, 2007, 4:49 AM

Great tutorial. I had worries about upgrading.

Craig | Feb 19th, 2007, 10:35 AM

Thank you so much for this article. A few months back, i went through this process - and basically became stuck at around about your "hair pulling" comment - which is suitably descriptive.

Well, you solved the final part of my puzzle. In my case, i had figured out it was to do with the ordering - but had missed the modification to the "StaticFile" handler.

Thanks for saving me another few hours of hair pulling. :)

Mads Kristensen | Feb 28th, 2007, 9:14 PM

This is great. It really help me. Thanks a lot.

NiHique | May 16th, 2007, 10:03 PM

Thank you! It solved my problems with urlrewriting.net in IIS7 and forms authentication! I was stuck in ordering .... thanks again!

classifieds | May 28th, 2007, 4:55 AM

Excellent thanks. I gave up with this back in November with the beta and reinstalled xp. Got a new machine now, and this solved it.

Note. If you have Vista 64bit then make sure you point to the 64bit version of the isapi dll otherwise it wont work.
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll

Also, when reordering, it didnt alway move the wildcard all the way to the bottom on first attempt, but needed two goes at it. Wierd. Anyway thanks again.

Web Design Glasgow | Jun 4th, 2007, 2:13 PM

Hi, thanks for your write up. Is ASPNET ISAPI a rewriting module built into IIS6/7? And does it depend on ASP.NET, or can you use it with ASP as well.

Finally, is there a way to reference a list of associations between an IDs and Names, such that when I have an ID in the querystring, I can replace is with the name?

Could you, for example, publish your rewrite rules, if you think they might help?

Cheers from Glasgow!

Mark S. Rasmussen | Jun 4th, 2007, 5:35 PM

@Glasgow
It is built into IIS6/7 ASP.NET, it will not work for vanilla ASP.

There is no standard builtin way to rewrite URL's containing names to belonging ID's. My rewriting heavily depends on RegEx to match the type of page that's being requested, and then a database lookup is made to determine the proper ID's:

// Check for category blog listing
m = Regex.Match(path, "^/blog/(?<category>[a-zA-Z]{1}[a-zA-Z0-9\\-]+)/?$");
if (m.Success)
htc.RewritePath("/blog_categorylist.aspx?CategoryID=" + DB.GetScalarString("SELECT CategoryID FROM tblBlogCategories WHERE FriendlyTitle = '" + m.Groups["category"].Value.Replace("'","''") + "'"));

Free Wii Girl | Jul 18th, 2007, 2:25 AM

What's the advantage of removing file extensions (and having files appear like folders)? I'm in the process of reworking my Free WIi site and this is something I've considered, but I don't want to run the risk of bringing up the wrong file. I'd appreciate feedback from anyone with more experience.

Mark S. Rasmussen | Jul 18th, 2007, 2:48 AM

There are several advantages.

- It's easier for users to remember the adresses.
- You can hide the actual folder structure, increased security as well as an abstraction for the functionality below.
- You can make slashable URL's more easily than normally.

That's the most important points, though there are probably a lot more. You won't risk anyone bringing up the wrong file as long as you code it properly.

Paolo Labellarte | Oct 11th, 2007, 10:11 AM

What's about rewriting the url of gif,jpg and so on.
I followed your suggestions, but using urlrewritingnet I receive always error 404 because, I think, they are always processed by StaticFileModule, moving up the wild card mapping the framework can' ececute these files and receive "Failed to Execute URL".
So if url rewrited contains also images pointing to virtual url, no way, it doenst't work. Isn't it ?

Ryan | Oct 22nd, 2007, 9:47 AM

Has anyone else noticed that when doing this in vista, any time RewritePath is used, it causes a full postback to the rewritten URL? In IIS 6 I know that I could use it, and not see the double post in something like fiddler. With IIS7, I do see it.

Kevin | Nov 29th, 2007, 5:34 AM

Thanks for the great article, it saved me a lot of time as well setting up an eCommerce site on IIS7 that is traditionally on IIS6 with URL rewriting and everything configured around that.

AgentJ | Jan 14th, 2008, 11:55 AM

You are a star!!!

Alexei | Apr 5th, 2008, 7:32 PM

Excellent! This is just what I was looking for and it worked perfectly. Thanks for taking the time to document this. Digg'd

dukou | Apr 10th, 2008, 3:21 PM

Thank you~

ASP.NET | Apr 21st, 2008, 1:38 PM

Thanks for this post!
Just what i was looking for..

Mike Irving | May 1st, 2008, 11:34 PM

Great article, your process makes the setup a doddle!

IIS 7 seems to give and take quite a lot, but on the whole I like it.

Mike.

E. B. | Jun 9th, 2008, 12:39 PM

I see IIS released the URL Rewriting module
http://learn.iis.net/page.aspx/461/creating-rewrite-rules-for-url-rewrite-module/

automatic article generator | Jun 24th, 2008, 6:26 PM

Very useful,current now I still using IIS6.

Lawrence Staff | Jul 8th, 2008, 4:46 PM

I've followed your excellent instructions & now my url rewriting works fine now but default pages aren't. If I say go to http://localhost/testsite or http://localhost/testsite/ I get the "Failed to execute URL" error message but if I go to http://localhost/testsite/default.aspx it's fine. Do I need to replicate the default page functionality in my url rewriting code now?

Lawrence Staff | Jul 8th, 2008, 5:15 PM

I've now amended my error handling in global.asax.cs to redirect to path + default.aspx if the error is a "Failed to Execute URL" error. It's nasty but it's only needed on my local version.

eCommerce Consulting | Jul 10th, 2008, 2:31 AM

Almost a year later and I still find this article useful. Don't ever take this down =)

Mark S. Rasmussen | Jul 10th, 2008, 11:24 AM

@Lawrence,
To do this hack, we basically bypass any of the existing modules - including the default page module. As you're onto yourself, you'll have to recreate the default page functionality yourself.

@eCommerce Consulting
I use my own article now and then as well, it's going nowhere :)

adu | Aug 5th, 2008, 6:29 AM

Is there any update for this post? I have the same problem as yours. I couldnt find any sample codes that works on IIS 7 to make asp file URL REWRITE

Sam | Aug 7th, 2008, 7:40 AM

Instead of creating your wildcard hander as an ISAPI handler why don't you create a managed handler pointing to System.Web.UI.PageHandlerFactory thus negating the need to run is Classic ASP mode... am I missing something?

Mark S. Rasmussen | Aug 7th, 2008, 8:40 PM

@Sam,

As you'll notice I mention a couple of times in the first sections of the post, I'm well aware that this hack is not the correct way of solving the issue. However, this was a fresh installation of Vista back in 2006, I had a website I needed to make some changes to, and I didn't really care to do a lot of rewriting - especially not as it was going to run on IIS6 on the production server.

Jd | Aug 9th, 2008, 3:52 AM

I have been trying to get this to work in windows vista 64bit and so far no luck. I am not sure what I am doing wrong, I have followed your steps and still no luck.

I either get the following error
HTTP Error 404.4 - Not Found

or

failed to execute url

depends on whether or not I use the 64bit isapi or not.
and I have the wildcard set up to use the following isapi file

C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll

Any help you can give on this would be appreciated. Thanks.

Mark S. Rasmussen | Aug 9th, 2008, 3:25 PM

@jd,
The 404 might be because you do not have a default file handler after having it setup like this. This / will no longer get mapped to /default.aspx - just a guess.

Failed to execute URL should contain more info on what's going wrong. Have you by any chance set your IIS to run in 32bit mode? That'll require you to select the 32 bit DLL's instead of the 64 bit ones.

JD | Aug 9th, 2008, 3:59 PM

How do you set up IIS 7 in 32bit mode? I didn't even think that was possible, but I have only being getting into IIS 7.0, so I could have set it 32bit mode without realising I did it. :)

As to the 404, correct me if I am wrong, but did I miss read the article. I was under the impression that the setup allowed you to do extentionless urls, and that with .aspx wouldn't be handle by the statichandler.

What I am trying to use is urlrewriter.net component, which works perfectly in xp, but under the version of windows that I am using it gives me the weird errors called out above.

Mark S. Rasmussen | Aug 9th, 2008, 8:49 PM

You can do extensionless urls, but the files still need to be there. Somehow a file has to handle the request, and you have to provide the mapping between an arbitrary request and a specific file. Normally, when you go to /folder/, the file /folder/default.aspx will be invoked due to the default file handler in IIS7/IIS6. When you strip out this handler, your request won't be handled at all and you might get a 404 error. Thus, your handler needs to make sure it handles the /folder/ request to some file - not necessarily default.aspx though.

I have no experience with urlrewriter.net so it might be a specific problem in regards to that component. If you've followed my instructions on every point, it should work normally.

JD | Aug 10th, 2008, 6:18 AM

Yep, that was what it was, as sson as i created a folder and set up a default page on the folder. It worked, I guess I misread the post originally now that I see it working.

Pity though, because urlrewriter works very well under xp, but I have not found much on how to get it to work in Vista. Thank you for your help.

Mark S. Rasmussen | Aug 10th, 2008, 12:37 PM

I'm pretty sure urlrewriter.net can also do the default file mapping. Although I don't have any hands on experience with it, I know lots of people recommending it, and default file handling is a pretty basic feature requirement.

John Bailo | Aug 15th, 2008, 8:55 PM

I'm trying to use a URLRewriter in IIS 6.0

The issue is it works in a virtual directory but not at the root/website level. The wildcard appmap to aspnet_isapi.dll doesn't seem to fire when applied at the website level -- I just get a 404 error. Is this your experience? Any suggestions for me?

Mark S. Rasmussen | Aug 16th, 2008, 4:44 AM

Wildcard mapping certainly works at the website level as well. Make sure you've setup the wildcard mapping at the website level as well, and not just the vdir.

Also, rule out the basics first - setup a global.asax that just Respond.Ends to make sure it's hit, and nothing else is affecting it.

mizzo | Sep 18th, 2008, 3:51 PM

Thank you, this article solved my problem. I didn't know that handlers are in specified order. Or better, I didn't noticed order link in IIS7 ;-)

Murat Atay | Sep 21st, 2008, 4:28 PM

Thanks for the tip.

Wetter | Oct 16th, 2008, 4:12 PM

Good article. Exactly this I find long time.

kral oyun | Nov 4th, 2008, 7:32 PM

Yep, that was what it was, as sson as i created a folder and set up a default page on the folder. It worked, I guess I misread the post originally now that I see it working.

Pity though, because urlrewriter works very well under xp, but I have not found much on how to get it to work in Vista. Thank you for your help. thanksss

Dennis Wong | Nov 8th, 2008, 5:54 PM

Hi Mark,

Your last comment on "Please notice that this is a hack. This is not the way URL rewriting is supposed to be done under IIS 7. " is quite a concern for me.

Doesn't this URLRewriter work properly with IIS7?

I can't find any other suitable URLRewriter, except for URLRewriting.net, which is in a foreign language.

I do not really want to "hack" the server to do something...

Please advise.

Thanks!

Evtim Grigorov | Nov 20th, 2008, 5:50 PM

Hi all,

I haven't read all the comments. I had the same fuckin problem. Without being sure, I suspect it may be causing by some kind of unability to read the URLRewrite type and name from the web.config file.

What I did without being very knowledgeable about this is to go to IIS7 -> mysite -> MOdules and then "Add managed module".
Type there the name/type as they are in your web.config. It may wanr you the type is not found but don't pay attention. Save the changes and give a try to reload the page.
It worked for me just great.

aaron | Jan 12th, 2009, 5:09 AM

great and well written. it was so easy to follow the instructions, i've had it setup for iis6 but needed the help to convert it to iis7.
thank you.

Daniel Saidi | Jan 13th, 2009, 10:41 AM

A million thanks - this really saved my day when looking into EpiServer CMS 5 R2 on Vista/IIS7.

A quick note, however. In the EpiServer project, we are targeting IIS6. In fact, all developers save me are running XP/IIS6. So, since the fixes will affect web.config, it is best to check out the file non-exclusively and then make sure to not check it, since that will cause problems with IIS6.

Since the fixes are quickly applied, it is better to repeat them each time the web.config is changed, instead of going through the trouble with dedicated IIS7 file versions etc.

Also, it is worth mentioning (altough it is probably obvious for most people) that sites that require this fix are best to be run as a separate site/application pool. If not, the fixes will affect the entire default web site.

Once again, a million thanks!

Mark S. Rasmussen | Jan 13th, 2009, 6:06 PM

@Daniel

Actually, in my testing I have had no problems checking in the web.config. What's added is a system.webserver section - which is valid under IIS6, but ignored. That means IIS7 will use the new settings while IIS6 will remain unaffected.

Also, as long as you don't make the change on the webserver level, it will only affect that single website, and thus it should not require you to move it into a different app pool, unless you have other reasons to do so (I do in my case since I need to the pool as x32 for unrelated causes).

gp | May 2nd, 2009, 3:59 PM

Thank you Thank you

This is an awesome post. You saved me from trashing a fresh install of 7 and going back to XP....Now that I have my IIS 6 apps working, need to figure out to integrate my other IIS 7 applications.

Juan | Jun 10th, 2009, 11:04 AM

Thanks for the help. I am using urlrewrinting.net's componant and by simply setting my application pool to clasic solved all my problems. Maybe it will work for someone else without having to go through all those steps.

Gabriel Porras | Jul 11th, 2009, 11:58 PM

Thanks Mark... It works for me!

We moved to a Win 64 so, as classifieds, I did need to point to Framework64. Both the new Wildcard Script Map and the existing .aspx.

Thanks a lot of!!

Robert | Sep 9th, 2009, 9:40 PM

@Evtim Grigorov
You say you copied type and name from the web.config?
What exactly did you do then?

@Others: Im trying to get this to work on IIS7 WITH extensionless URL's. Does anyone have an example web.config and the right configuration in IIS 7?

Kaan | Sep 19th, 2009, 10:31 PM

How can we access and control IIS? I think, hosting services don't accept this.

protienshow | Sep 26th, 2009, 10:52 PM

Million Thanks,

It took me whole afternoon for me to migrate II6 app to II7 using UrlRewritingNet.

This is an must read article for someone who want to get the UrlRewritingNet work in II7 as II6.

Christian Louboutin Sale | Oct 26th, 2009, 3:45 PM

We moved to a Win 64 so, as classifieds, I did need to point to Framework64. Both the new Wildcard Script Map and the existing .aspx.

Thanks a lot of!!

suresh | Nov 27th, 2009, 1:31 PM

I am using 64 bit windows 7 in my system. when i was using iis 6 ,the URL rewriting is working fine. Now I have changed everything as explained in the above.Even it is not working ,its working only for some URL'S only. For other's it shows "failed to execute url" errors.

Can anyone help me to solve this problem asap ?

Thanks.

Chris | Feb 2nd, 2010, 2:26 PM

Thank you - I've been trying to find the answer to this for a while now and your blog gave me everything I needed to know! I'm sure Windows Server 2008 is a great product, but I'm finding it so hard to work with!

Luke Stratton | Feb 15th, 2010, 8:02 PM

I have just followed these instructions and now everything works, except when I am MEANT to get a 404, I get a 'Failed to execute URL'. Is there a way to fix this?

Thanks

Tim | May 14th, 2010, 12:02 PM

Thank you!!!

Serdar TOROS | Jun 7th, 2010, 5:12 PM

excellent article for solving this problem,
thnx a lot...

Gus | Jun 7th, 2010, 7:27 PM

Excelent Article!! all is ok but i have error with rule extension .htm example:
<rewrite url="^~/(es|fr|en)/(website|website|website).htm" to="~/seccion-website.aspx?Lang=$1"/> the error is 404..
Any idea??
Many Thanks

Gus | Jun 9th, 2010, 2:05 PM

The problem has been solved, but now the problem is in www.misitio.com the error is "Failed to Execute URL." :-(( any ideas?? many thanks and sorry for my lenguage im spanish

casino avec des bonus gratuits | Jun 26th, 2010, 1:06 PM

We are working on permalinks – and I have same issue as Sayuri. How do we check to see if PHP is running on FastCGI. I think it is but not sure how to confirm.

chaosuk | Aug 2nd, 2010, 5:39 AM

your all wrong, you dont need to make any changes to iis7 to get urlrewriter working properly u just need to properly declare the module in web.config. Ensure you have the following:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRewriter" type="Intelligencia.UrlRewriter.RewriterHttpModule" />
</modules>
<validation validateIntegratedModeConfiguration="false" />
</system.webServer>
Doing it like this will allow you to use urlrewriter out of the box without any tweaking to any of the setup.

Add comment

After you have posted a comment, an email will be sent to the provided email address. Before your comment is activated, you will have to click the confirmation link within the email.

Name:

Email (only used for validation):

Website (optional):

Message:

Notify me when new comments are added:

Please type the following letters into the box below:  

Post!