Get MVC3 Razor Running on Mono

Updated 10-18-2011 – added some more common issues

I dug around a little to figure this out. Hopefully this will clarify all the steps required to get an MVC 3 Razor site running on Mono. The main pitfall I ran into was gathering the additional dependencies and excluding Microsoft.Web.Infrastructure assembly from my deployment. Overall though it’s not too difficult to deploy your MVC3 app.

In Summary:

  1. Install Mono
  2. BIN Deploy Website
  3. Configure Apache (or Xsp environment)
  4. Fire Up Your Server
  5. Errors You Might See

Install Mono

If you haven’t done this yet, go grab it from the Mono downloads page. You need to run at least Mono 2.10, preferably the latest release (2.10.2). For Ubuntu you can use the badgerports; or for Ubuntu, compile from source using a bash script I created. (Skip the MonoDevelop install).

 

BIN Deploy Your Website

For this, I just performed a traditional “Publish” from Visual Studio to a file system directory. Be sure to set these references to “copy local.”

  • System.Web.Mvc
  • System.Web.Helpers
  • System.Web.Routing

 

BIN Deploy Additional MVC3/Razor Dependencies

Just like Scott Hanselman mentions in his BIN deployment post, add these additional libraries found in the MVC3 RTM. On Windows, they install to C:\Program Files\Asp.Net.

  • System.Web.Razor
  • System.Web.WebPages
  • System.Web.WebPages.Razor
  • System.Web.WebPages.Deployment

 

NOTE: Do NOT copy the Microsoft.Web.Infrastructure assembly.  This assembly has been rebuilt in the mono library and will already be available to your app. 

 

Configure Apache/XSP

Once you have Mono runtime installed, setup your apache virtual host configuration. Setup a virtual host to use mod-mono-server4. If you installed Mono with a custom prefix (like my script above), then be sure and setup your virtual host environment. Here’s a sample virtual host configuration using the Mono install prefix of, “/opt/mono-2.10”.

<VirtualHost *:80>
  ServerName yourhostname

  DocumentRoot /srv/www/mvc3

  <Directory />
    Options FollowSymLinks
  </Directory>

  MonoServerPath mvc3 "/opt/mono-2.10/bin/mod-mono-server4"

  #optional debug mode
  MonoDebug mvc3 true 

  #be sure and set the prefixed mono paths here
  MonoSetEnv mvc3 MONO_IOMAP=all;PATH=/opt/mono-2.10/bin:$PATH;LD_LIBRARY_PATH=/opt/mono-2.10/lib:$LD_LIBRARY_PATH;  

  MonoApplications mvc3 "/:/srv/www/mvc3"
  <Location />
    Allow from all
    Order allow,deny
    MonoSetServerAlias mvc3
    SetHandler mono
    SetOutputFilter DEFLATE
    SetEnvIfNoCase Request_URI "\.(?:gif|jpe?g|png)$" no-gzip dont-vary
  </Location>
  <IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/javascript
  </IfModule>
</VirtualHost>

For running XSP manually, setup your shell environment with the correct prefix. Here’s a sample bash script.

#!/bin/bash
MONO_PREFIX=/opt/mono-2.10
GNOME_PREFIX=/usr
export DYLD_LIBRARY_FALLBACK_PATH=/lib:
export LD_LIBRARY_PATH=/lib:/opt/mono-2.10/lib:
export C_INCLUDE_PATH=/include:/include
export ACLOCAL_PATH=/share/aclocal
export PKG_CONFIG_PATH=/lib/pkgconfig:/lib/pkgconfig
export PATH=/bin:/opt/mono-2.10/bin:$PATH

 

When you’re ready to fire up Xsp4: save the script above to a file (in this case env.sh), enter a terminal, change your working directory to the web directory and enter the following:

$ source env.sh
$ xsp4

 

Fire It Up

Once everything has been deployed, fire up xsp4 or restart your apache2, all should be working.

 

Errors You Might See

  • System.Security.SecurityException: No access to the given key.
    • Delete Microsoft.Web.Infrastructure.dll from you bin directory.
  • No response from web server on request, but you do see errors in the log /var/log/apache2/error.log
    • Check to make sure all your dependencies are present in the bin folder and apache has read/execute access to them. (Ubuntu: www-data group).  Also read through the errors at the end of the file and see if something else is causing the problem. Sometimes I rename/delete error.log and then restart the server for a fresh log.
  • File request returns a 404 or asp.net missing assembly exception (but the file(s) actually exists)
    • Check your file permissions and make sure www-data group has read access to the files and read/execute to the directories involved.
    • find web-directory -type f exec chmod 664 {} \;
    • find web-directory -type d -exec chmod 775 {} \;
  • Cannot find View…  (but it really does exist…)
    • There are a few things that cause this. 
    • File permissions; make sure www-data can read the web files
    • missing Web.config (especially under ~/Views); this is what informs the compiler how to build the view templates.
    • Syntax error in a view (may cause other views not to render returning this error).
    • Missing assemblies (make sure you bin deploy the site with all the necessary Razor and WebPages dlls. Do not deploy Microsoft.Web.Infrastructure.
    • Layout/Master page being used doesn’t exist.
    • Getting: “The classes in the module cannot be loaded”,   Just delete System.Web.WebPages.Administration.dll from your local bin directory. (not required for this).

26 thoughts on “Get MVC3 Razor Running on Mono

  1. I run your solution on a physical server instead of a virtual environment. What do i need to do about the Configure Apache/XSP step?

    For running XSP manually, you have written a sample bash script. Is this just copy plaste if you have used the 2.10.5 installation script? If not how do i find out what prefixes i need. Is it a optional or must do step?

    With your solution, can it run a normal ASP.NET website? Or is it only capable to run ASP.NET MVC2 or 3?

    I think your projects (this) is a great project. But a shame that their isn’t a forum to support it.
    Also i ran your guide from http://www.integratedwebsystems.com/2010/11/setting-up-mono-2-8-with-asp-net-4-0-and-mvc2-on-ubuntu-with-mysql-membership/ and used the install script from http://www.integratedwebsystems.com/2011/08/install-mono-2-10-3-on-ubuntu-using-bash-script/#comments and then followed the http://www.integratedwebsystems.com/2010/11/setting-up-mono-2-8-with-asp-net-4-0-and-mvc2-on-ubuntu-with-mysql-membership/ guide again. But i have some issues i cant figure out. I don’t know if you expect people to have knowledge from this area to use this guide. Example i have 0 experience with ASP.NET server setup, XSP, Apache. And i find it difficult to use if i get in a unexpected situation, because information is scarse. In my humble opinion, and their is no forum support.

    Currently i have the error that, my files docent get read from /srv/www/ubuntu. But from /var/www/, also if i place my files in /var/www/ i get an error 500, or apache cannot find my index.aspx page, for some strange reason. Maybe this is because i uploaded a normal ASP.NET with no MVC2 or 3?

    Also in your 2.8 guide (i don’t really know if this is used with 2.10.5 since i cannot see that anywhere that tells so, so i used it since that seamed logic) you write First, open the ~/Models/AccountModels.cs file and remove all data annotations attributes from the three model classes’ properties. I would love an example of what an “data annotations attributes” is. You also write “write your own server-side validation.” is this optional or? For the page to run with mono on linux.

    I’m sorry if i am not your target group for using your guide. I have been trying for some time now to get ASP.NET running on linux. And this is the first decent guide i have found. Even tho i would love a little more info.

    Also last edit note.
    I used your install script 2.10.5, and you refer to this page for setting environment values. In the section Install Mono you have yet another install script. But no info on apache configuration as you do in your 2.8 guide. Is this because the script does this now? Or is it meant to go to this page. In the install mono section use the bash script their, and go in the 2.8 guide for the apache configuration? Also in these guides you don’t say if you still should publish in /srv/www/ubuntu/ or is this now /var/www/. Maybe its just me.

    Kind regards.

  2. All of those are great questions! To be honest, this all started out with a simple install script for 2.6.7 on ubuntu 10.10 (I think). But as versions were released, I started creating new posts for each version. However, the process in setting up Apache and ASP.NET (web forms or MVC 1, 2 and 3) is the same. So I typically refer back to previously written posts if I think it could apply.

    With all that said, I think you have a few things going on. First, these posts are time sensitive. For example, 2.4 did not support MVC 1, but 2.6.7 (MVC1) and 2.8 (MVC2) does with the exception that Data Annotations doesn’t work. Now, (2.10.5), I have found that they (MVC 1,2 & 3) indeed do work just fine. So you can leave the model validation for the Account related stuff in the default MVC project. MVC1 and 2 are pretty straight forward. You deploy your app along with tye System.Web.Mvc assembly (and maybe also System.Web.Routing). MVC3 is a little more involved, but it’s the same idea. You go grab the RTM of the MSPL release of MVC3 and drop in all the dependencies I noted in that post.

    The next big issue I think you’re having is the disconnect in my posts that talks about configuring Apache. I think I only have one or two of them that briefly skim over it. I apologize for that. I’ll try to get something out there to detail that better. The overview of what you need to do is create a new configuration file and make it available for the apache configuration. By default, Ubuntu sets up two folders: One for sites-available and one for sites-enabled under the path /etc/apache2/. Typically, you create just a regular text file for your virtual host configuration and place it in the “available” directory and then create a symbolic link in your “enabled” directory. You can also, more straight forward, just create the file in the sites-enabled directory instead. Either way, once it’s in this directory, you can restart the apache2 service and it will attempt to load your new virtual host configuration automatically. Definitely go checkout the Apache 2 documentation site for more info on how to just play with apache virtual hosts in general. You’re seeing the default site under /var/www/index.html because you haven’t overriden the default website. Setting up a virtual host for *:80 and your ServerName would fix that. Use the mod_mono config tool on the mono-project website too. It will create the base config you need. Just don’t forget to modify the path to your custom mono and the MonoEnv directive I mentioned another post.

    One more thing related to Apache: the mods-enabled and mods-available work the same way. After instaling Mono 2.10.5, you should see a mod_mono.conf in your /etc/apache2 directory. You need to move that file to your mods-enabled directory and restart apache. This will enable the mono handler.

    Hopefully there’s some information there that will get you rolling. If all else fails, it never hurts to try using the badgerports repository and then simply doing: sudo apt-get install mod_mono mono-dev to get everything installed and setup under the default system. Then you don’t have to mess with any of the custom environment settings and you can just focus on the apache config and deployment files for your website.

  3. Nice write up. I’m doing something similar and ran into a problem when apache tries to load the System.Web.Mvc.dll. It says, “Could not load type’System.Web.Mvc.ViewPage’.” I looked in the gac directory for the System.Web.Mvc.dll and there is a 2.0….., but no 4.0….. entry like the others have. (I tried mono-server2 also.) I am running Ubuntu and have mono 2.10.5 working for a non MVC site. The debug page says it is running ASP.NET Version: 4.0.30319.1. I tried copying the dll to the mono 4.0 lib dir as well but it didn’t help. Any idea what I could do to fix this?

  4. Hi @Mark McKinney,

    Well, it should not require the MVC assemblies to be in the GAC. If you’re running MVC3, then you should see a 3.0 DLL in your bin directory of your website after you set that reference to “Copy Local”. It should always look there first for assemblies that are not in the GAC. Along with System.Web.Mvc.dll, you’ll need the other ones I mentioned above. You should never have to touch any of the Mono lib folders or the GAC directly.

    Do you have a Windows / Visual Studio machine available to test this site? I get the feeling this may have been an upgraded MVC2 to MVC3 site? I could be totally wrong; but if that were the case, there’s a few other things you’ll have to change to make that work (even for the Windows side). Here’s a blog post I found about it.

    Definitely only run the mod-mono-server4 (MVC3 requires 4.0 runtime). Copy local any assembles (listed above) that you’ll need for MVC. That “should” work. :)

    Good luck!

  5. Thanks @Nathan ,

    I’ve bin deployed before, the dlls are there. And the security looks ok to me as well. You are correct that this has been upgraded to MVC 3. But it works fine on IIS. It’s been a long time since I converted it, but I may have upgraded the references by hand. Again, they work fine on IIS. I just copied the running wwwroot working stuff to Ubuntu, setup apache – and got that error.

    One difference is that I have the apache app in a subdirectory. It seems like it can’t find my bin directory for some reason. Perhaps I’ll have to try and set it up as the root app….

  6. @Mark McKinney
    Okay cool. I’ve had issues myself when upgrading sites. Typically it’s lingering library references in either the root web.config or the Views web.config. Sometimes I’ve just fallen back to creating a brand new project and importing the rest of the files into the new project; just to start fresh. IIS /.NET is pretty forgiving on the asp.net side. My observation is that the JIT in IIS only builds what it needs. But on the Mono side, the whole thing is pre-compiled so sometimes you’ll see hidden errors for things you didn’t know about on the IIS side.

    Another thing you can try is using the badgerports.org version of Mono. They’re up to 2.10.5 now. Checkout my latest post regarding the EC2 install. It’s nearly the same as this one, except it goes through the details of using badger ports.

  7. @Mark McKinney I’ve always set mine up as a separate virtual host (like websites in IIS). But it should work just fine as an alias/virtual directory. If you used a custom build of Mono, then make sure your environment variables are set correctly in your config. I mentioned badger ports, because it will make itself the default Mono for the platform, so you don’t have to mess with setting up your environment at all. It’ll just use the default /usr/bin/… prefix.

    Hope that helps!

  8. Hey @Nathan

    I finally got back to this, after converting everything to razor and some other stuff. And its sort of working: virtual dirs have path issues, but it is working as the root url except for the actual root url. That is, all urls with paths work, but the root url doesn’t. I tried setting the DirectoryIndex but it doesn’t help. It works on IIS so I shouldn’t have to mess with my routes. Should be an apache config setting but I don’t know what….

    Any ideas?

  9. @Mark,

    I don’t believe I even set a DocumentIndex file. Make sure you’re using a config section. This takes the “routes” from the requested URL and hands them off to the Mono handler. From there, the default MVC route handlers will take over. Here’s a section of my config (I used the Mono-project mod_mono config tool to do mine, which may require a few minor tweaks if you’re using a custom mono path).



    Allow from all
    Order allow,deny
    MonoSetServerAlias mvc3
    SetHandler mono
    SetOutputFilter DEFLATE
    SetEnvIfNoCase Request_URI "\.(?:gif|jpe?g|png)$" no-gzip dont-vary

    My default routes work with this. Make sure you have a default route specified in your global.asax.cs file.

  10. Hey thanks. I did all that but still no go. So finally I fixed it by removing the Default.aspx file in the root dir that specifically says to not remove it. I guess it was trying to load that file and failed.

    Now I’m contemplating following your EC2 post. Looks pretty involved though. I think Heroku is easier and still free up to 750 hrs/mo.

  11. @Mark,

    Ah yeah. That’s definitely something that lingered from the MVC 2.0 project. New projects in MVC 3.0 don’t have Default.aspx files anymore. I don’t believe any of my current projects [running on Mono] do either. Something I’ve done while converting older projects is create a brand new sandbox project with the new version and compare configs, file layout, etc. I’ve also just created new projects and then imported all the important stuff from the old project; just to make sure it’s correct for the new version. Sometimes those lingering settings for the old version will really hang up stuff.

    The AWS thing is pretty fun to play with. I treat AWS as the ad-hoc, full control, detail oriented type solution for folks who want that kind of control. Azure, while more expensive is a great solution if you want to spin up a distributed solution fast and don’t want the headache of configuring it all yourself. I haven’t tried any others yet. I’ve heard good things about AppHarbor, which I think runs on AWS right now.

    My thought for a solution I’m playing with is to setup on AWS and wire up a simple MemCached handler for session/cache, MongoDB for data persistence, but it’s all going to require some work to get rolling. I envision some kind of auto-scaling config that will allow me to spin up many instances without interacting with the systems… But this is me just talking about something I haven’t death with yet. ;)

  12. I just received a promo offer for MSDN and read that part of the benefits is free azure access. Only 375 hrs for pro, but 750/1500 hrs for premium/ultimate. Can’t afford more than the pro though. Promo is $354/yr for 2 years.

    AWS looks best for sites that get a lot of traffic. A memcached system sounds fast. Still I’d rather spend my time on dev vs systems engineering – until I need to…

  13. Hi Nathan

    Thanks for documenting the process for getting Mono working with MVC3. Out of curiousity I’ve tried a similar process for ASP.NET MVC4 (beta) on Mono 2.10.8.0 but there are new assemblies (ie System.Net.Http.* ) that I haven’t been able to get working or use Mono equivalents. Have you heard of anyone having any luck with this? It will be great having the new mobile web API working under Mono!

  14. @Reid
    That’s a great question. I have not tried it yet myself. I’ve been avoiding it in fear of the shiny syndrome. ;) If there are any new assemblies, I would attempt bringing them over via “Copy Local” to see if they run on Mono. This usually works unless the assemblies were IL merged or if they contain platform invokes not yet supported. If you get it working, post back here. I’m curious for certain.

    There are also some alternatives for mobile. You can build it yourself via the WC3 standards for mobile. (I’m guessing, but this is likely what MVC4 did with helpers). Or your an wire in jQuery Mobile which auto manipulates your DOM based on view resolution and changes elements to be more fitting for mobile resolutions. Hanselman talks about this somewhat; in the post linked, he talks about different mobile view engines for MVC3 that are spec compatible with 4… You might give those a spin.

    Good luck!
    -Nathan

    Thanks

  15. Hi Nathan,

    Thanks for this great blog post. It saved me a lot of time.

    I had a weird problem. Every time I build or debug, the Microsoft.Web.Infrastructure is automatically copied to the Bin folder. Need to delete it every time manually. Is there a better way to deal with this? I am using MonoDevelop 3.0.3.2 and the framework is Mono 2.10.9 (tarball). Thanks for your help.

  16. Never mind my question above, I figured it out. I had that dll file put in the Solution folder and Mono always copied it to the Bin although I didn’t find anywhere reference that .dll file. Thanks again for the great post.

  17. Hi @SO Glad you got it working! Yeah those extra assemblies are only copied over if they’re in the bin folder. From the Visual Studio side, I don’t even thing that assembly is referenced directly. Nice job getting it working!

    I need to post and updated version of this article. Ubuntu 12.04 is about 1000x simpler because you don’t need to install Mono manually at all. It comes pre-packaged with a version that runs MVC3 just fine.

    Thanks!

  18. @Patrick Herrington
    Nice man! Thanks for sharing! I’ve actually been all over the place lately. I started setting up Makefiles for my projects so I could use git hooks and remote deployments. “git push production master” would push to my production server, pull latest master, compile, and do a publish-like copy over to the production directories via bash script (git hook). It’s neat stuff. With the Makefile you can use any editor/IDE. Even Sublime hooks nicely into it.

    In the past month or so I’ve been using MonoDevelop solely at work for MonoTouch/iOS stuff. It’s much nicer than I expected. I haven’t used it for Razor/MVC3 yet though. I’ve been using a lot of Re# and AppCode lately though too and those tools tend to spoil you in the IDE worlds.

    Thanks!
    -Nathan

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>