Setup Mono, mod_mono, and Apache – An Introduction do Windows developers

First and foremost: I’m not a Linux developer, but I love using Linux to run my asp.net web applications through mono. And I use it more and more every month. So even though I might not be a Linux Wizard, I can probably help other Windows developers understand how to work on Linux. Anyway, here goes.

Installing Mono on Linux

I’m using the SUSE Linux distribution; specifically I’m using the 64 bit Amazon edition of Suse Linux. I’ve found it easier to deploy mono to Suse than other distributions. It might not be true anymore, and it might have been easier on other distributions if I knew more about Linux in general :-)

However, installing mono under Suse is really easy.

First, you just have to add the relevant repository. Later we can install mono from this repository:

zypper addrepo http://download.mono-project.com/download-stable/openSUSE_11.4 mono-stable
zypper refresh --repo mono-stable

Important: You might experience that you are prompted to trust the repository key. Hit ‘a’ to always trust the key. Now upgrade the repository:

zypper dist-upgrade --repo mono-stable

Finally, install mono from the repository:

zypper install -y mono-complete

On my AWS Micro instance this takes a couple of minutes. This should do the trick. Type “mono –version” to ensure that mono has been installed.

Installing Apache with Mono on Linux

Now that Mono is installed, it is time to install the Apache Web Server. Apache works quite different from IIS, but you can actually come to appreciate it :-)

We’ll start with the basic installation of Apache:

zypper install -y httpd
touch /etc/apache2/sysconfig.d/include.conf
rcapache2 start
zypper install -y xsp
zypper install -y mod_mono

In the first line httpd is installed. On Linux, things that ends with a “d” are usually “daemons” – somewhat equivalent to Windows services. So httpd is the Apache HTTP Daemon.

rcapache2 is a command for performing basic commands on Apache, for example the “start” command. It takes other parameters such as “stop” and “restart”.

Xsp is the mono web server. It can be nice to install for various testing purposes, but it shouldn’t be necessary. I usually always install it.

Finally the “mod_mono” component is the Apache module that runs mono. Apache plugins are often prefixed by “mod_”, for example mod_ssl.

Now that Apache is installed, we need to configure a VirtualHost on Apache. A VirtualHost is somewhat equivalent to a Virtual Directory in IIS. Actually the name VirtualHost probably makes more sense than Virtual Directory, I think.

Basically, the VirtualHost is given a PORT number, and you point it to some location on the file system. Anything ingoing on the specified port will then be executed by the web application running at the specified location on the file system. To glue these two together (to establish an actual runtime for executing your mono project), you need help from mod_mono. More on this below.

The VirtualHost is configured in a domain specific language which is almost an XML structure. In the beginning I found it hard to accept that this looks so much like XML, but it is far from being XML compliant. My advice is just to accept this. Yes, it’s ugly, but that’s how it is:-)

The actual file structure of the configuration files depends between the Linux distributions, but on Suse Linux the VirtualHosts are placed in the /etc/apache2/conf.d folder. Suse Linux is setup to automatically load all configuration files ending in .conf in the conf.d folder. So, go to this folder by typing:

cd /etc/apache2/conf.d

Create a file with a custom name ending in .conf – for example myWebServer.conf.

Open the file and paste this code (replace ServerName and ServerAdmin with your own values):

<VirtualHost *:80>
  ServerName ocase.net
  ServerAdmin mortenmaateDELETE_THIS@hotmail.com
  DocumentRoot /srv/www/mysite
  MonoServerPath mysite /usr/bin/mod-mono-server4
  MonoApplications mysite "/:/srv/www/mysite"
  <Location "/">
    Allow from all
    Order allow,deny
    MonoSetServerAlias mysite
    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>

Now, apache is configured with mod_mono. This VirtualHost will listen to all incoming traffic on port 80. You can specify the server name, the server admin in accordance with your own data.

The DocumentRoot directive is important and points to the folder on your file system that contains your web site. We haven’t created the web site yet, but we’ll do so in a minute. The MonoServerPath specifies which executable will run mod_mono. The number 4 signals, that we’re using the .NET 4 runtime. Mono has runtimes for other .NET versions as well.

The Location directive takes the parameter “/” which maps to the root location of the web site folder (specified in DocumentRoot above). Here some apache specific stuff can be set. I’ll cover the details of this in a later blog post.

Create your site

Allright, the DocumentRoot now points to a location on your server. In my code above it points to /srv/www/mysite. Create this folder and go to it by typing:

mkdir /srv/www/mysite
cd /srv/www/mysite

Create a file named index.html by typing:

echo "<h1>Hello world</h1>" >> index.html

Finally, you need to allow the webserver to access  the file and restart apache:

chmod 777 /srv/www/mysite -R
rcapache2 restart

Now you should be able to access your service in a normal browser, and it should return Hello World.

You can deploy your ASP.NET application to this folder, and it should work.

If you experience that changes you make are not taking effect, try restarting apache.

Making Apache start automatically on reboot

The Apache Daemon does not automatically start itself on boot. Often this is what you want for a web server. To enable this, type:

chkconfig --level 2345 apache2 on

 

Write csharp (C#) in command prompt console

I just found this mono tool today – it’s included in the mono installer.

If you’ve added your mono path to the environment variables, simply type csharp in the command prompt, and you’ll get:

C:\Documents and Settings\morm>csharp
Mono C# Shell, type "help;" for help

Enter statements below.
csharp>

And you’re good to go! I have a feeling that I’ll be using this feature extensively for both Mono and .NET development.

Amazon AWS Route 53 XSD’s

I’ve extracted some xsd’s for the route 53 api’s and uploaded them here:

http://www.box.net/shared/4pevbg7padukeganjya4

Next version of OCometNet

As you might know, OCometNet is a server to client notification framework.

Currently you can use it for chat applications.  But in the next version I’m working on extending this, so that it’s possible to update the view model on another client.

Check out this very short demo to see a preview of the upcoming functionality:

Registry settings in mono on Linux

Obviously, Linux does not have a registry. However, just like the .NET framework, Mono provides the Microsoft.Win32.Registry class for accessing the registry. So how does it work on Linux?

First, I would like to state that personally, I never use the registry. I hate using it for lots of reasons. But I do have situations where third party frameworks use the registry, and I use these framework on Mono/Linux, and hence I become dependent of it.

System wide settings

The system wide settings which are shared between users, e.g. HKCR, are stored in /etc/mono/registry. E.g. in /etc/mono/registry/ClassesRoot/. In this sub directory sub keys are stored as sub folders, and values are stored in xml files with the name values.xml:

<values>
<value name="Content Type"
type="string">application/msword</value>
</values>

This example is from /etc/mono/registry/ClassesRoot/.doc/values.xml.

User settings (e.g. HKCU) are stored in the same way, but in the sub folder  .mono/registry to the users home directory instead, e.g. ~/.mono/registry/CurrentUser.

Finally, if you are running a web app, please remember to ensure correct security settings if the web app should have access to specific or all registry settings. For example:

chmod 777 /etc/mono/registry/ClassesRoot -R

This will allow read and write access to ClassesRoot and all sub folders. Often you can loosen up on Linux registry settings security compared to Windows, but please remember to be careful.

Mono bug using custom model binder (IModelBinder)

Gosh, this one required an hour or two.

I use a custom model binder to parse the http body for some json.

The error I got was smth like a BAD REQUEST http error, and in apache’s error_log an entry said mth like: Invalid URI in request { myjson } PUT /MyUrl HTTP/1.1.

In my controller the code looks like this:

public JsonResult Update([ModelBinder(typeof(GenericModelBinder))]Case casefile) { … }

I resolved the problem by adding a default value for casefile, i.e.:

public JsonResult Update([ModelBinder(typeof(GenericModelBinder))]Case casefile = null) { … }

It must have something to do with the order of the routing – it seems that in mono the custom ModelBinder is applied in some step after the routing itself, and my request does not map to any URL –> route pattern since the ModelBinder graps stuff from the HTTP Body, and not from the url itself.

Anyway, now it works :-)

Mono bug with dynamic key word (CS1061)

I had this bug: CS1061: Type `object’ does not contain a definition for [some property].

It took me a couple of hours to figure out that this is a minor bug in the “var” keyword in mono.

The problem occurs when “casting” a dynamic variable to var. In this process it is being treated as an Object by the compiler. E.g. something like:

dynamic d = some obj
var v = d;
v.MyProperty // CS1061 exception

In .NET, however, this works fine. To resolve the issue, rename the var keyword to dynamic.