How to Host an ASP.NET Application with Mono
Contents
Mono Project Web Page
Part 1: Downgrading from .NET Framework 4.5 to 4.0
If you want to run .NET programs on Mac and Linux environments, Mono is making this possible and their latest 3.12.0 release is a great indicator of the possibilities that Mono is bringing to .NET community.
This is the first of a three part series to detail how to use Mono to host ASP.NET applications on Linux and Mac OSX. We are using Visual Studio Community 2013 to develop our sample ASP.NET MVC WebApi application. Visual Studio Community 2013 defaulted to .NET framework 4.5 when we created the new project. We quickly realized that Mono 3.12.0 does not support .NET framework 4.5. It does support .NET framework 4.0 and this is where our fun began.
STEPS TO DOWNGRADE AN ASP.NET MVC APPLICATION FROM 4.5 TO 4.0 .NET FRAMEWORK
As mentioned above, Mono 3.12.0 does not work with .NET framework 4.5, so we needed to downgrade our application to use .NET framework 4.0. These are the steps we performed to downgrade our application:
- Run your application and ensure it is working with the .NET Framework 4.5
- Right click your MVC project and Select Properties
- Under Application change the Target Framework to .NET Framework 4
- Select Yes to confirm the Target Framework change
- Close and reopen your project
- Run these commands in the Package Manager Console
Uninstall-Package Microsoft.AspNet.Identity.Owin Uninstall-Package Microsoft.AspNet.Identity.EntityFramework Uninstall-Package Microsoft.AspNet.Identity.Core Uninstall-Package EntityFramework Uninstall-Package Microsoft.Owin.Security.Twitter Uninstall-Package Microsoft.Owin.Security.OAuth Uninstall-Package Microsoft.Owin.Security.MicrosoftAccount Uninstall-Package Microsoft.Owin.Security.Google Uninstall-Package Microsoft.Owin.Security.Facebook Uninstall-Package Microsoft.Owin.Security.Cookies Uninstall-Package Microsoft.Owin.Security Uninstall-Package Microsoft.Owin.Host.SystemWeb Uninstall-Package Microsoft.AspNet.WebApi.Owin Uninstall-Package Microsoft.Owin Uninstall-Package Microsoft.AspNet.WebApi.HelpPage Uninstall-Package Microsoft.AspNet.Mvc Uninstall-Package Microsoft.AspNet.WebPages Uninstall-Package Microsoft.AspNet.Razor Uninstall-Package Microsoft.AspNet.Web.Optimization Uninstall-Package Microsoft.AspNet.WebApi Uninstall-Package Microsoft.AspNet.WebApi.Webhost Uninstall-Package Microsoft.AspNet.WebApi.Core Uninstall-Package Microsoft.AspNet.WebApi.Client Uninstall-Package Owin
- Save your project
- Close and reopen Visual Studio
- Reopen the project
- Run these commands in the Package Manager Console
Install-Package Microsoft.AspNet.Razor -Version 2.0.30506 Install-Package Microsoft.AspNet.Mvc -Version 4.0.30506 Install-Package Microsoft.AspNet.Web.Optimization -Version 1.1.3 Install-Package Microsoft.AspNet.WebApi -Version 4.0.30506 Install-Package Microsoft.AspNet.WebApi.Client -Version 4.0.30506 Install-Package Microsoft.AspNet.WebApi.Core -Version 4.0.30506 Install-Package Microsoft.AspNet.WebApi.HelpPage -Version 4.0.30506
You will be prompted on whether you want to overwrite _ViewStart.cshtml when you install the Microsoft.AspNet.WebApi.HelpPage. Select option A to overwrite _ViewStart.cshtml. Open packages.config and search the file for targetFramework="net45". Replace any references with targetFramework="net40"
I got an error that stated I needed to re-install Newtonsoft.Json. I was able to remedy the error by running this in the Package Manager Console
Install-Package Newtonsoft.Json
Now that you have cleaned up the NuGet package references it is time to clean up the code that came with the WebAPI 2.2 .NET Framework 4.5 template.
- Delete the following files:
Models > IdentityModles.cs App_Start > IdentityConfig.cs App_Start > Startup.Auth.cs App_Start > Startup.cs Providers > ApplicationOAuthProvider.cs Controllers > AccountController.cs Controllers > ValuesController.cs Results > ChallengeResult.cs Models > AccountBindingModels.cs Models > AccountViewModels.cs
We need to update the code in App_Start > WebApiConfig.cs.
Remove
using Microsoft.Owin.Security.OAuth;
Remove
config.SuppressDefaultHostAuthentication();
Remove
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
Remove
config.MapHttpAttributeRoutes();
We need to update the Global.asax.cs code:
//GlobalConfiguration.Configure(WebApiConfig.Register); WebApiConfig.Register(GlobalConfiguration.Configuration)
If you try to run your application now, you will see this error:
Parser Error Message: An error occurred creating the configuration section handler for system.web.webPages.razor/host: Could not load file or assembly 'System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
To fix this error we need to update the versions referenced in the Views > Web.config file as follows:
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" /> <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" /> </sectionGroup> ... <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
Now your application should run and the Home view should render. Let's add a new WebApi controller to ensure that we can invoke the RESTful service.
Add a new sample WebApi controller named TestController.cs Start your application and note the port used on localhost Test the GET http method call by going to http://localhost:<<port>>/api/test. You should see this response:
<ArrayOfstring xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays"><string>value1</string><string>value2</string></ArrayOfstring>
Part 2: Hosting on Mac OSX
Keep in mind that Mono doesn't currently support .NET Framework 4.5, so follow the instructions in Part 1 of this series if you need to downgrade to .NET Framework 4.0.
ENVIRONMENTS AND SOFTWARE VERSIONS USED
- Operating Systems - Windows 8.1, Mac OSX 10.9.5, Ubuntu Server 14.04 LTS (HVM)
- Mono 3.12.0
- Visual Studio Community 2013 Version 12.0.31101.00 Update 4
- ASP.NET MVC 4
- Apache 2.4
- VMware Fusion 7.1.1
We are using an iMac as our development machine. It is running OSX 10.9.5 and has VMware Fusion installed. We have a Windows 8.1 64-bit VM that we access through Fusion. The Windows 8.1 VM has Visual Studio installed and that is where we wrote our ASP.NET MVC WebApi application. Visual Studio Community 2013 defaulted to .NET framework 4.5 when we created the new project. We quickly realized that Mono 3.12.0 does not support .NET framework 4.5. It does support .NET framework 4.0 and this is where our fun began. Follow the instructions in Part 1 of this series if you need to downgrade to .NET Framework 4.0.
INSTALLING MONO ON MAC OSX
Now that we have a ASP.NET MVC 4.0 application we can deploy that code to a Mac OSX machine and ensure that Mono will allow that application to run. We followed the Install Mono on Mac OSX instructions on the Mono site.
We installed the .pkg and followed the installation wizard. Then, we tried to run through the Hello World examples to ensure they were working. All of the sample programs ran without error except for the Gtk# Hello World example. We noticed this error:
System.DllNotFoundException: gtksharpglue-2 at (wrapper managed-to-native) Gtk.Container:gtksharp_gtk_container_get_focus_child_offset () at Gtk.Container..cctor () [0x00000] in <filename unknown>:0
We were able to fix this error by adding the following lines to the /Library/Frameworks/Mono.framework/Versions/3.12.0/etc/mono config file:
<dllmap os="osx" dll="glibsharpglue-2" target="/Library/Frameworks/Mono.framework/Versions/Current/lib/libglibsharpglue-2.so" /> <dllmap os="osx" dll="gthread-2.0.0" target="/Library/Frameworks/Mono.framework/Versions/Current/lib/libgthread-2.0.0.dylib" /> <dllmap os="osx" dll="gthread-2.0" target="/Library/Frameworks/Mono.framework/Versions/Current/lib/libgthread-2.0.dylib" /> <dllmap os="osx" dll="glib-2.0.0" target="/Library/Frameworks/Mono.framework/Versions/Current/lib/libglib-2.0.0.dylib" /> <dllmap os="osx" dll="glib-2.0" target="/Library/Frameworks/Mono.framework/Versions/Current/lib/libglib-2.0.dylib" /> <dllmap os="osx" dll="glibsharpglue-2" target="/Library/Frameworks/Mono.framework/Versions/Current/lib/libglibsharpglue-2.so" /> <dllmap os="osx" dll="gtksharpglue-2" target="/Library/Frameworks/Mono.framework/Versions/Current/lib/libgtksharpglue-2.so" /> <dllmap os="osx" dll="gobject-2.0.0" target="/Library/Frameworks/Mono.framework/Versions/Current/lib/libgobject-2.0.0.dylib" /> <dllmap os="osx" dll="gobject-2.0" target="/Library/Frameworks/Mono.framework/Versions/Current/lib/libgobject-2.0.dylib" /> <dllmap os="osx" dll="gtk-quartz-2.0.0" target="/Library/Frameworks/Mono.framework/Versions/Current/lib/libgtk-quartz-2.0.0.dylib" /> <dllmap os="osx" dll="gtk-quartz-2.0" target="/Library/Frameworks/Mono.framework/Versions/Current/lib/libgtk-quartz-2.0.dylib" />
RUNNING ASP.NET MVC 4.0 APPLICATION ON MAC OSX
With the sample programs working it was time to try out my MVC application. We deployed the code from the Windows 8.1 VM to a new folder on the iMac. Then, opened terminal and ran this:
xsp4 --root <<parent folder path to the MVC bin folder -- do not include /bin in path>> --port 9000
While the xsp server is running you can test your application using http://localhost:9000/api/test url. Replace "test" with the name of your controller. PART 3 is not published yet : follow the link for it http://www.bloomspire.com/blog/2015/3/6/how-to-host-aspnet-applications-on-linux-part-2-hosting-mac-osx