Friday, October 29, 2010

MVC 2 automatic deployment on IIS 5 (Windows Xp)

When you're deploying MVC application on IIS 5 you have to add wildcard '.*' mapping associated with isapi dll. IIS 6 and IIS 7 do that job for you for free.

Basically when you're doing it with your own hands you have to configure mappings in IIS manager. The scheme step by step is:
1. Open IIS manager.
2. Find your Website/Virtual Directory.
3. Open Properties window of that site/directory and find Configure button and add mapping for extension ".*" targeting aspnet_isapi.dll located in C:\Windows\Microsoft.NET\Framework\\

After that your extensionless URLs will be picked up by IIS and passed to MVC framework.

Now to the problem: what if I'm using WebDeploy to install my website on multiple machines that are all running IIS 5 (WinXp)? There must be some way to automate the process of adding of wildcard mapping to newly created website. And there is.

After doing some research I've bumped into the page on quite an old web site named IISFAQ.com. There they use VBScript to add any extension mapping scheme to existing website (http://www.iisfaq.com/Default.aspx?tabid=2792).

The script isnt very readable (its VBScript after all), so to narrow it down here is a simplified version that just adds wildcard mapping:
option Explicit

Dim ObjectPath,IISOBJ,NewScriptMaps
' Path to website/virtual directory, note that '1' before the root is the number of website used
ObjectPath = "IIS://localhost/W3SVC/1/ROOT/Test"

' Reading script maps that associate file extensions to applications
' and adding wildcard *. This wildcard should be processed by ASP.NET
' so we point at aspnet_isapi.dll. This way we can use ASP.NET MVC
' with extensionless URLs like http://localhost/home/index.
SET IISOBJ = getObject(ObjectPath)
NewScriptMaps = IISOBJ.ScriptMaps
Redim preserve NewScriptMaps(Ubound(NewScriptMaps)+1)

' 1 in the following line means that checkbox that says "Check that file exists"
' will be unchecked. That's a requirement, because ASP.NET MVC address points at
' the controller and method, not an actually existing file.
NewScriptMaps(ubound(NewScriptMaps)) = "*,C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll,1,GET,HEAD,POST,DEBUG"
IISOBJ.ScriptMaps = NewScriptMaps
IISOBJ.SetInfo

if (ERR <> 0) then
WScript.Echo "TERMINATING -- Error setting data - " & Err.Description & " (" & Err & ")"
WScript.Quit(1)
end if

This script will add wildcard mapping to virtual directory named "Test" of the first website on the local machine. All you have to do now is to integrate this .vbs into your deployment script, enjoy.

P.S. This script works with IIS 6 as well. Though if you're using .NET 4.0 there is no need to use wildcard mapping with IIS 6 unless you have dots in your URL scheme (like "http://localhost/Home/Index.Test"). IIS 5 requires wildcard mapping no matter what your addresses look like.