About your host

Photo of your host - Charles Vallance Charles Vallance is a web developer with a slight case of OCD when it comes to nice clean standards compliant html and code.

Badges

twitter / cvallance
My articles have been featured in The Morning Brew - Daily .NET News and Views

Tag Cloud

more tags...
January 2008 Entries

Ok, after a slight push from Travis, I decided to put aside some time to live up to my promise and post an entry on how to enable extensionless requests on the new ASP.NET MVC framework using IIS 5.1 & 6.

I'm starting where my last post, ASP.NET MVC on IIS 5.1 (XP Pro), left off. So if you haven't got the MVC framework working on IIS 5.1 or 6 with extensions, have a gander at my last post and make sure its all working.

What we currently have (following after my last post) is links like /Home.mvc/About which are working because we've mapped the .mvc extension to the ASP.NET application, so IIS knows it's for ASP.NET and can fire it off in that direction, but what we'd ideally want is just having the link look like /Home/About (without any extension). Currently if you try an extensionless request like that, IIS just doesn't know what to do with the request or where to send it, so it returns a 404.

Enter URL rewriting!

I'm going to use Helicon Tech's ISAPI_Rewrite 3. The lite version, which I'm going to use, is free but has limitations (which you can read about here) but should be fine for what we want to do. The full version is only $99 US per server... cheap as chips if you ask me!

ISAPI_Rewrite offers the same syntax and behavior as mod_rewrite on Apache (which is a good thing :-). If you don't know anything about mod_rewrite or are completely new to the whole URL Rewriting idea, I would recommend you read up on some material - here would be a good place to start, or good old wikipedia.

Anyway, lets start.

First off you'll want to download ISAPI_Rewrite 3 from here (just grab the lite version) and install it. You shouldn't run into any problems... touch wood. If you do, go back to their documentation for troubleshooting advice.

Once it's installed, open up the httpd.conf file in your favourite text editor (Notepad++ is my fav :-)) and add the following lines. Note that if you used the .msi installer, the httpd.conf file should be in the Program Files\Helicon\ISAPI_Rewrite3\ directory.

RewriteEngine on 
RewriteBase 
RewriteRule ^Home/(.*?)$ Home.mvc/$1

What this RewriteRule is doing is intercepting any request that starts with "Home/" and replaces the "Home/" part with "Home.mvc/". Once it's done this, IIS handles the request and sees the .mvc extension, so it fires that request off to ASP.NET.

Brilliant.

So go back to your browser and try and visit the http://localhost/Home/About address on your local machine. Hopefully you should be met with the same page as if you would have written http://localhost/Home.mvc/About. Yay! Now do that for all your different controllers... Just make sure none of your controllers are called Styles, CSS, Scripts etc etc ;-)

But there is still a problem... anyone picked it yet?

You see, our incoming request, "/Home/About", is being rewritten, by ISAPI_Rewrite, to "/Home.mvc/About" and is then being passed to ASP.NET and it's then being handled by the ASP.NET MVC routing engine. It should then match the following routing rule:

RouteTable.Routes.Add(new Route
{
    Url = "[controller].mvc/[action]/[id]",
    Defaults = new { action = "Index", id = (string)null },
    RouteHandler = typeof(MvcRouteHandler)
});

So this will go off to the "About" action on the "Home" controller. Fantastic... but what happens when you go the other way? What happens when you get the ASP.NET MVC routing engine to write the links for you? That's right, it'll have the .mvc extension thrown onto the end of any requests that match the rule.

Hmmm, not cool because it basically renders all of what we've done with the URL rewriting useless!

Not all is lost though. You see, the ASP.NET MVC routing engine tests each incoming and outgoing URL against the RouteTable from top to bottom (which is why you need to write them from most specific to least specific)... So if we throw in a different rule, say the exact same rule without the .mvc part, that should be evaluated first and find it as a match and then the outbound links shouldn't have .mvc in them.

Something like this:

protected void Application_Start(object sender, EventArgs e)
{
    RouteTable.Routes.Add(new Route
    {
        Url = "[controller]/[action]/[id]",
        Defaults = new { action = "Index", id = (string)null },
        RouteHandler = typeof(MvcRouteHandler)
    });

    RouteTable.Routes.Add(new Route
    {
        Url = "[controller].mvc/[action]/[id]",
        Defaults = new { action = "Index", id = (string)null },
        RouteHandler = typeof(MvcRouteHandler)
    });

    RouteTable.Routes.Add(new Route
    {
        Url = "Default.aspx",
        Defaults = new { controller = "Home", action = "Index", id = (string)null },
        RouteHandler = typeof(MvcRouteHandler)
    });
}

Glorious.

So, that's a start... it's nice and simple and hopefully a good place to get you going. I'm open to suggestion as to different ways of going about it... I'm no mod_rewrite or regex guru by a long shot!

Technorati Tags: ,

Ok, so while Scott Hanselman's MVC How-To Screencast is downloading, I thought I'd write a quick blog about getting ASP.NET MVC working on XP Pro and IIS 5.1. Although I haven't tested it, this fix should also work on IIS 6 boxes as well. When you create a default ASP.NET MVC project and use IIS 5.1 on XP Pro to serve up the pages, the default page (http://localhost/) loads up just fine but when you try and navigate to the 'About Us' page you'll get a 'The page cannot be found' 404 error. To remedy this (without going down the ISAPI filter road to get extensionless requests cranking) and use the .mvc extension as suggested, read on. Firstly you must edit the Global.asax.cs file and change the default routing rule to the following (you're just adding .mvc after [controller]).

RouteTable.Routes.Add(new Route
{
    Url = "[controller].mvc/[action]/[id]",
    Defaults = new { action = "Index", id = (string)null },
    RouteHandler = typeof(MvcRouteHandler)
});

Now after you've done this you'll have to associate the .mvc extension to ASP.NET. Firstly you must get to the properties of your site by right clicking on your 'Default Web Site' and selecting 'Properties' IIS51-site-properties

Then on the Home Directory tab, hit the Configuration... button

IIS51-site-configuration

To map the .MVC extension to the asp.net engine, we must find the location of the asp.net executable. The easiest way of doing this is to find where the .aspx extension is mapping to.

So to do this, on the 'Mappings' tab, on the 'Application Configuration' popup, find the '.aspx' extension and hit 'Edit'. From this box, copy the full executable location like so.

IIS51-excutable-copy

After you've done that, hit 'Cancel' and you should be back at the 'Application Configuration' popup. From this screen hit the 'Add' button and paste in the previous Executable location, then fill out the rest of the details like the screen shot below and make sure that the 'Check that file exists' check box is NOT ticked.

IIS51-extension-association

After that you should be ready to rock.

The great thing about the ASP.NET MVC routing engine is that you won't need to change any of the links, they will now be updated so that they include the .mvc extension, e.g. http://localhost/Home.mvc/About

Not pretty or ideal but it's quick and it works! I'll try and get a extensionless fix up soon.

Technorati Tags: ,,