Deploying an ASP.NET MVC website on IIS 6 and .NET 2.0
As posted before, this website has been built using the new ASP.NET MVC framework, which is based on the .NET framework 3.5 and internally uses a lot of the new C# 3 syntax. Additionally, the MVC Routing module works a lot better on IIS 7 than on the older IIS 6.
So, in order to run Klopfenstein.net on Aruba.it, which offers shared "medium trust" IIS 6 hosting on Windows Server 2003, I had to go through some hacking.
Getting MVC to run on .NET 2.0
Fortunately, .NET guru Scott Hanselman wrote a very useful post about the subject a couple of months ago which includes all info you need to run MVC on .NET 2.0.
Targetting .NET 2.0
The first step is to actually target the 2.0 .NET framework from your Visual Web Developer project properties:

This ensures that the code you write for your website will compile on the .NET 2.0 compiler of your hosting service. Unfortunately, this also means you will not be able to use all the fancy new language syntax of C# 3.0 (lambda expressions, object inline initialization, automatic properties and so on...). Anyway, all code you compile to a .dll file (using Visual C# or whatever) can use any arcane language syntax (or any language in fact) as long as it targets the 2.0 framework.
Just remember that all code in your App_Code folders and in your Views you must use the standard .NET 2.0 syntax or your host's compiler will not understand your code.
Including MVC references
Finally, some parts of MVC (namely System.Web.Mvc.dll and System.Web.Routing.dll) reference the System.Core.dll library which is only available in .NET 3.5. The very simple solution is to simply take the dll library from your computer and put it into the website's Bin folder:

C:\windows\assembly\GAC_MSIL\System.Core\3.5.0.0__b77a5c561934e089
This procedure is not supported by Microsoft, but should be legally acceptable (as noted on Scott's blog post). Another solution would be to take the System.Core.dll file from the open source Mono Project and include it.
Deploy the website on IIS 6
The main problem with IIS 6 on shared hosting is that the web server will not call the ASP.NET engine to render your pages, because all nice URLs generated by MVC do not map to files on the server.
Steve Sanderson has an interesting blog post about the problem and suggests 4 possible solutions (apart from switching to IIS 7):
- Change IIS 6 settings and enable "wildcard mapping" to ASP.NET: in this case all HTTP requests are routed through ASP.NET and then handled by the routing module. On the one hand this has obvious performance implications and secondly it won't work because we have no access to IIS settings in shared hosting.
- Using ISAPI_Rewrite to rewrite requests before IIS interprets them: again, this doesn't work on my host.
- Put a custom filename extension in all URLs, for instance adding ".mvc" at the end of every route in the routing module. This requires to add a file extension mapping to IIS 6 and isn't possible on shared hosting.
- Simply use the .aspx extension in all URLs: this will work because you don't need any custom mapping in IIS and .aspx requests are automatically handled by ASP.NET.
This way every URL includes the .aspx extension and is not completely clean, but it's clean in your code (just change the routing) and works on all hosts. For instance:
public void SetupRoutes(){
RouteTable.Routes.Add(
new Route("home.aspx",
GenRouteDict("controller", "Home", "action", "Index"),
new MvcRouteHandler())
);
RouteTable.Routes.Add(
new Route("home.aspx/{page}",
GenRouteDict("controller", "Home", "action", "Page", "page", null),
new MvcRouteHandler())
);
}
/// <summary>Create a RouteDictionary instance using couples from an object list.</summary>
/// <remarks>Useful because the fancy Dictionary constructor syntax is not supported in .NET 2.0.</remarks>
public RouteValueDictionary GenRouteDict(params object[] s) {
IDictionary<string, object> ret = new Dictionary<string, object>();
for (int i = 0; (i + 1) < s.Length; i += 2) {
string a = s[i].ToString();
object b = s[i + 1];
ret.Add(a, b);
}
return new RouteValueDictionary(ret);
}
Solve the 404 error on homepage
The last routing problem is that requests to the root "/" of your website won't be handled correctly and return a #404 "not found" error. You can handle this special case either by adding an event listener to every request or by putting a Default.aspx WebForm in your root folder with this code:
public partial class _Default : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) {
Context.Response.Redirect("home.aspx", true);
}
}
This will redirect all request to the correct full URL.
Compression and Caching
When using IIS 6 without "wildcard mapping" the requests for static files (like .js code, images and .css style sheets) will be handled by the web server and not by ASP.NET. On shared hosting you usually have no control over the server's settings and therefore can't control how those files are served (that is, unless you change their extension to .aspx or include them in your MVC routing).
All other requests though will go through the ASP.NET pipeline and can be cached and compressed as you like. Omar Al Zabir's blog includes a post about these issues and show some code that can be used to decorate your controller's action in order to compress their output or to cache it. My current, very simple, implementation is the following:
public class CompressedAttribute : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext filterContext) {
HttpRequestBase request = filterContext.HttpContext.Request;
string acceptEncoding = request.Headers["Accept-Encoding"];
if (string.IsNullOrEmpty(acceptEncoding)) return;
acceptEncoding = acceptEncoding.ToLowerInvariant();
HttpResponseBase response = filterContext.HttpContext.Response;
if (acceptEncoding.Contains("deflate")) {
response.AppendHeader("Content-encoding", "deflate");
response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
}
else if (acceptEncoding.Contains("gzip")) {
response.AppendHeader("Content-encoding", "gzip");
response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
}
}
}
Your decorated controller would look like this:
namespace Controllers {
[Compressed]
public class ArticleController : Controller {
//...
}
}
Lowercase routes
One last issue with MVC URLs is that, if you follow the .NET guidelines in writing your controller's code, you end up with camel-cased routes whereas usually URLs on the web are always lowercased. Check out this blog post by Nick Berardi to get his LowercaseRoute class and simply use it when defining your routes instead of the standard Route class.
That's it
Your MVC website should now work flawlessly on your shared host with .NET 2.0 and IIS 6. ![]()
Currently I'm trying to make Lucene.NET work (and NHibernate.Search) but unfortunately the library requires "full trust" right now. Perhaps I'll have to take their code apart and recompile it...




I have ASP .net MVC website created on my machine ,it is runnig fine on my machine ,all links are working but when I hosted is on IIS 5.1 that time home page is assible from other pc on network but all its Links(url routing) is not working,Images are not getting loaded , css is not working.. Plz provide the help if a any... How can make my web app workable ?