Asp.Net MVC4 on Mono & Xamarin/MonoDevelop on Mac – The C# Template Project

Update Jan 2014: Go straight to github for MVC Templates for .Net 4 and .Net 4.5 or see asp-net-mvc4-net-framework-version-4-5-c-razor-template-for-mono-on-mac-and-linux for more recent notes.

I've been trying for a while to get this working. It all seemed so-near-and-yet-so-far. But here is the Visual Studio 2010 C# Asp.Net MVC4 Template Project which works on my Mac and (thanks to comment from Stephen) on Linux :
Visual Studio 2010 Asp.Net Mvc4 CS# Web Application Template modified for Mono

There's a list of issues which frustrated earlier attempts but the above link is to a project that does build and run on my Mac. Things to make it work included:

  • Got the latest Xamarin Studio, previously known as MonoDevelop
  • Mono version: I got MVC4 on Framework version 4 running on Mono 2.10.12; and MVC4 on Framework 4.5 on Mono 3.2.5. Nb I'm not sure whether everything related to async is currently working, but many web apps wouldn't want to use async.
  • There's a list of potential issues to address described in this stackoverflow post, I think what I did was just:
    • Delete Microsoft.Web.Infrastructure.dll from the bin directory
  • I also removed Entity Framework References. As of Jan 2014 that's not yet done on the Mono, although this may change shortly.
  • At first I commented out the line AreaRegistration.RegisterAllAreas(); in global.asax.cs Application_Start because it caused an error which appeared to refer to Entity Framework but that might just have been because I had removed System.Web.DynamicData too, so I put DynamicData back in.
  • The StyleBundles failed with a typo, or rather a case-sensitivity issue. A lot of .Net code is written on the assumption of a case-insensitive file system, but mono on *nix will usually have a case-sensitive filesystem, so you have to start being pedantic about getting the case correct. For instance App_Start/BundleConfig.cs referred to the file Site.css as site.css, so it wasn't found until I corrected it.
  • Having taking the 'intranet' template which uses Windows authentication, I changed the web.config line <deny users="?"></deny> to <allow users="?"></allow>. But this gives you no security. The simplest route back to a secure website is to instead put in forms authentication, I don't yet have a solution for windows authentication on mono.
  • I included all the nugetted package dlls in the zipfile, except that I deleted the EntityFramework stuff.

Kudos to all who worked so hard to make MVC4 on Mono possible. And of course to those who made MVC4 possible at all.

Using Castle Windsor DI for controllers in an Asp.Net WebApi Project

There are contrary signals on the web regarding Window DI and the new-ish MVC-ish WebApi IDependencyResolver. Fortunately, by late 2012 Mark Seemann summarised the state-of-the-art: don't use it.

The reason: it doesn't allow your DI container to properly manage lifetimes. Instead, do this:

public class WindsorCompositionRoot : IHttpControllerActivator
{
    private readonly IWindsorContainer container;
 
    public WindsorCompositionRoot(IWindsorContainer container)
    {
        this.container = container;
    }
 
    public IHttpController Create(
        HttpRequestMessage request,
        HttpControllerDescriptor controllerDescriptor,
        Type controllerType)
    {
        var controller =
            (IHttpController)this.container.Resolve(controllerType);
 
        request.RegisterForDispose(
            new Release(
                () => this.container.Release(controller)));
 
        return controller;
    }
 
    private class Release : IDisposable
    {
        private readonly Action release;
 
        public Release(Action release)
        {
            this.release = release;
        }
 
        public void Dispose()
        {
            this.release();
        }
    }
}

and wire it up with this line during Application_Start in Global.asax.cs

GlobalConfiguration.Configuration.Services.Replace(
    typeof(IHttpControllerActivator), new WindsorCompositionRoot());

Using Windsor for plain old MVC html pages inside WebApi projects

if you are using MVC controllers with views for html pages as well as IHttpControllers in your WebApi project, then you need to know that the WebApi controllers & activation is a quite separate subsystem from the MVC controllers. You still need the usual WindsorControllerFactory to hook Windsor into the MVC pages as well as the above for the WebApi controllers.

Code for a WindsorControllerFactory can be found in a couple of places, but this is from the Castle Windsor tutorial for Asp.Net 3 and is still valid for Asp.Net 4:

using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Castle.MicroKernel;
 
public class WindsorControllerFactory : DefaultControllerFactory
{
    private readonly IKernel kernel;
 
    public WindsorControllerFactory(IKernel kernel)
    {
        this.kernel = kernel;
    }
 
    public override void ReleaseController(IController controller)
    {
        kernel.ReleaseComponent(controller);
    }
 
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
        {
            throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
        }
        return (IController)kernel.Resolve(controllerType);
    }
}

and again, you must hook it into the application object in Global.asax.cs

private static IWindsorContainer container;

//These lines should be called during Application_Start
container = new WindsorContainer().Install(FromAssembly.This());
var controllerFactory = new WindsorControllerFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);

// And this in Application_End:
container.Dispose();

Asp.Net MVC Project Guids

The famously unhelpful Visual Studio error message 'The project type is not supported by this installation' usually means that there is something you don't have installed. But it doesn't tell you what.

You can work out what you're missing if you know the Guids to look for in the project file. Look for a line near the top of the file something like this:

<ProjectTypeGuids>{E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>

After which you can decode the Guid using either the table here:

Guid Tools Needed to Open Project Build references
{E53F8FEA-EAE0-44A6-8774-FFD645390401} Asp.Net MVC 3 System.Web.Mvc 3.0.0.0
{E3E379DF-F4C6-4180-9B81-6769533ABE47} Asp.Net MVC 4 System.Web.Mvc 4.0.0.0
{349c5851-65df-11da-9384-00065b846f21} Web Designer

Or the more extensive list at http://www.mztools.com/articles/2008/mz2008017.aspx. If you're stuck try http://google.com/search?q=visual+studio+project+type+guid+list