Mark S. Rasmussen improve.dk
Dec 11
2006

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).

iis7ur1_2

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.

iis7ur2_2

Now enter the “Handler Mappings” section:

iis7ur3_2

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.

iis7ur4_2
iis7ur5_2

Your StaticFile handler should now look like this:

iis7ur6_2

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:

iis7ur7_2

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:

iis7ur8_2
iis7ur9_2

Click OK and click Yes at the confirmation dialog:

iis7ur10_2

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

iis7ur11_2

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

iis7ur12_2

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:

iis7ur13_2

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:

iis7ur14_2

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

iis7ur15_2

“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:

iis7ur16_2

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:

iis7ur17_2

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

iis7ur18_2

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.

Mark S. Rasmussen
I'm the Technical Lead at iPaper where I cuddle with databases, mold code and maintain the overall technical responsibility. I'm an avid speaker at user groups & conferences. I love life, motorcycles, photography and all things technical. Say hi on Twitter, write me an email or look me up on LinkedIn.
Comments
  • Bryan Peters December 12, 2006

    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 December 12, 2006

    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 December 12, 2006

    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 January 11, 2007

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

  • Sergey P. January 14, 2007

    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 February 6, 2007

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

  • Aaron February 13, 2007

    Great tutorial. I had worries about upgrading.

  • Craig February 19, 2007

    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 February 28, 2007

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

  • NiHique May 16, 2007

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

  • classifieds May 28, 2007

    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:WindowsMicrosoft.NETFramework64v2.0.50727aspnet_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 June 4, 2007

    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 June 4, 2007

    @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 July 18, 2007

    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 July 18, 2007

    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 October 11, 2007

    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 October 22, 2007

    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 November 29, 2007

    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 January 14, 2008

    You are a star!!!

  • Alexei April 5, 2008

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

  • dukou April 10, 2008

    Thank you~

  • ASP.NET April 21, 2008

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

  • Mike Irving May 1, 2008

    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. June 9, 2008

    I see IIS released the URL Rewriting module
    learn.iis.net/…

  • Lawrence Staff July 8, 2008

    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 July 8, 2008

    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 July 10, 2008

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

  • Mark S. Rasmussen July 10, 2008

    @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 August 5, 2008

    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 August 7, 2008

    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 August 7, 2008

    @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 August 9, 2008

    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:WindowsMicrosoft.NETFramework64v2.0.50727aspnet_isapi.dll

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

  • Mark S. Rasmussen August 9, 2008

    @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 August 9, 2008

    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 August 9, 2008

    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 August 10, 2008

    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 August 10, 2008

    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 August 15, 2008

    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 August 16, 2008

    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 September 18, 2008

    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 ;-)

  • kral oyun November 4, 2008

    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 November 8, 2008

    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 November 20, 2008

    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 January 12, 2009

    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 January 13, 2009

    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 January 13, 2009

    @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 2, 2009

    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 June 10, 2009

    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 July 11, 2009

    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 September 9, 2009

    @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 September 19, 2009

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

  • protienshow September 26, 2009

    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.

  • Chris February 2, 2010

    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 February 15, 2010

    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 14, 2010

    Thank you!!!

  • Serdar TOROS June 7, 2010

    excellent article for solving this problem,
    thnx a lot…

  • Gus June 7, 2010

    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 June 9, 2010

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

  • chaosuk August 2, 2010

    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.

  • dane killian May 30, 2011

    Hi all,

    Thanks for the article.

    I found that all that was needed to do, was update the application pool my site was running in, from Integrate, to Classic, and that seams to have solved it.

  • Parminder Singh August 26, 2011

    Hi,

    Firstly thanks for your help and post.

    I have implemented the steps you have written. But I am still getiing the error "Failed to execute URL". I ahve put wildcard entry below the staticfile. Please help me out on this. I urgently need to impelent this.

    Thanks & Regards,
    Parminder Singh

  • Jason Millikan September 2, 2011

    Kick ass article! You helped me get my site up just in time for the demonstration! Thank you!

  • Shane January 27, 2012

    Thanks for the post, it was helpful. I’m running IIS 7.5 on Windows 7 and to get it to work, the newly created wildcard had to be before static and the static needed to be "*" to work under my circumstances.

  • dan April 8, 2012

    this goes some way to solve my problem however in ASP.net 2.0 on IIS 6.0 i was able to handle static requests using ASP.net , rewrite them and then seemingly the static file would be served.

    Your solution is the closest I’ve got to getting this working however with this if I have /myfile.css and I would normally rewrite this to /somefolder/myfile.css this doesnt happen.

    essentially on IIS 6 I took an imaginary url rewrote it according to where the database said it was physically stored but then it looks as if the static file handler serves it.

    Any thoughts on this difference?

  • Repairman April 21, 2012

    @chaosuk Correct! Thanks allot. Application works in ‘Integrated mode’
    You don’t need to run UrlRewriter in ClassicMode when you just add the following in the web.config:

    <modules runAllManagedModulesForAllRequests="true">
    <add type="Intelligencia.UrlRewriter.RewriterHttpModule,Intelligencia.UrlRewriter" name="UrlRewriter" preCondition="" />
    </modules>

    With IIS 7, 7.5 be sure you look at this too:
    social.technet.microsoft.com/…

    Happy coding!

  • karthik May 30, 2012

    this post was Written on December 11, 2006. But still its helping large number of people including me. What a great post. Thank you man.

  • pankaj verma June 19, 2012

    it works, but i have problem to open its sub folders.
    please suggest me.

  • Vali June 27, 2012

    THERE IS A SIMPLE TRICK with II7 and 404 can be made to execute whatever aspx you want (like it did in IIS6)

    You JUST have to add THIS:
    errorMode="Custom" existingResponse="Replace"
    to the UNDOCUMENTED <httpErrors> !!!
    it will look like this

    <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" subStatusCode="-1" />
    <error statusCode="404" prefixLanguageFilePath="" path="/My404.aspx" responseMode="ExecuteURL" />
    </httpErrors>

    I found it here:
    http://forums.iis.net/p/1153365/1886004.aspx

  • Rups October 13, 2012

    Due to your amazing post i just came to know exactly my problem.

    But still i have problem.
    hope u help me.

Leave a Comment