If you've recently tried to install the latest version of BlogEngine.NET on Mono, you would have noticed that the URL rewriting does not work for posts, but does work for categories.

This comes down to a bit of an oddity in the mono ASP.NET runtime. It turns out that if you have a path like /posts/2009/03/09/slug.aspx and an actual file called /posts.aspx exists in the root site, mono gets confused and mangles the path.

In your URL rewriting IHttpHandler you'd expect the path returned by context.Request.Path to match what was requested, but in reality Mono will give you /posts.aspx.cs/2009/03/09/slug.aspx instead. This is obviously a bug in Mono, but it's fairly easy to work around.

To fix the issue in BlogEngine.NET, open UrlRewrite.cs in BlogEngine.Core and modify your context_BeginRequest method to look like this:

private void context_BeginRequest(object sender, EventArgs e) {
    HttpContext context = ((HttpApplication)sender).Context;
    string path = context.Request.Path.ToUpperInvariant();
    string url = context.Request.RawUrl.ToUpperInvariant();
    // fixes an oddity in mono where .aspx.cs is added
    path = path.Replace(".ASPX.CS", "");
    url = url.Replace(".ASPX.CS", "");
    ...
}

Compile and deploy!

A while ago I did a tutorial on installing Mono 1.2.6 on Ubuntu. As it turns out, installing Mono 1.9.1 follows the exact same process. You can thus use the 1.2.6 tutorial as is, just replacing the version numbers in the files you need to download with the corresponding 1.9.1 versions. The only notable exception is mod_mono which is only version 1.9. All full list of exact file locations is available from here: http://ftp.novell.com/pub/mono/sources-stable/

I haven't yet tested the installation procedures on Ubuntu 8.04, but I assume they'd be pretty much the same. If I'm wrong in that assumption, please let me know.

I've had some requests for a tutorial on installing BlogEngine.NET on Linux (and in particular Ubuntu).

Getting BlogEngine.NET itself to run is the easy part, the hard part is getting the latest release of Mono compiled from source on Ubuntu and getting mod_mono and apache2 configured together.

So to that end I'm starting a series of tutorials, beginning with the installation of Mono 1.2.6 from source on Ubuntu 7.10 (Gutsy Gibbon). These instructions should also work on Ubuntu 6.10/7.04. The next tutorial will be focused on installing BlogEngine.NET itself.

Here's the first tutorial: Installing Mono from source on Ubuntu 7.10 (Gutsy Gibbon)

If you should have any issues with the tutorial, either contact me directly or add a comment on this post, and I'll attempt to guide you through any problems you may have. Any feedback should also help in creating a troubleshooting section for the tutorial to help others out that may have the same issues.

BlogEngine.NET 1.3 was released just before Christmas. This version supports Mono on Linux out of the box, so if you've been waiting to try it on Linux, I would suggest you try it right away!

If you are about to run on Linux, I would suggest that you get the latest sources as there were a few late fixes for the new Extension Manager on Mono. You need to get version 1.3.0.1 or later. As for Mono, you also need to get the latest version (1.2.6 as of writing), as the latest release has some major performance enhancements that are required for a stable Mono/BlogEngine.NET environment. See this post for more information.

Mono 1.2.6 has been officially released. The release features some memory usage improvements which of course has been an issue to me as far as getting BlogEngine.NET to run stably on Linux is concerned.

I've upgraded this server to 1.2.6 and so far so good. The installation was fairly trouble free (which says a lot on Linux), and so far memory usage does appear to be down quite a lot from what it was. I've only just upgraded, so we'll have to see what happens in the next couple of hours/days.

There was one issue I had with the upgrade however. I removed my existing libgdiplus installation in order to upgrade to the new version available for download. After compiling and installing all the new libraries, Mono was complaining about not finding gdiplus.dll. The cause of the issue appears to be that libgdiplus by default installed into /etc/local/lib instead of /etc/lib. As this is where Mono is installed as well, I opted to fix the issue rather than re-install into /etc/lib. The Mono-Project has a page dedicated to finding missing libraries, which is where I found most the information to fix the issue.

Fixing the DLLNotFoundException path issue

Firstly, edit /etc/ld.so.conf and make sure that /etc/local/lib is included in the file.

Then run ldconfig to update the dynamic linker cache (I've noticed that SuSE runs ldconfig after every install. It may be a good idea to run it every time you install anything by compiling from source).

You should also check your /etc/mono/config file to make sure that the DLL mapping is correct. In my case it wasn't. You should see a line that looks similar to this one in the file:

<dllmap dll="gdiplus.dll" target="/usr/local/lib/libgdiplus.so.0" />

If it isn't there, add it. Make sure the path is correct!

I had to reboot my server in order to get everything working correctly after the changes. This may not be necessary in your case, but it doesn't hurt to be sure.

As far as I'm concerned, all Mono needs now for prime time server use is the Compacting GC. Lets hope that it gets delivered quickly!

I'm still no closer to solving the problems I'm having with mod_mono. It means having to restart the apache server at least twice a day, leaving large gaps in the day where this blog is completely inaccessible.

Until such time as I can trace and resolve the mod_mono issue, I've decided to resort to an ugly hack. Yes, you guessed it: automatically restarting the server if the blog goes down.

There are native Linux solutions to this very problem. System Integrity Monitor is one of them, but I was unable to make it work for my mod_mono driven virtual host, so I decided to roll my own solution.

The idea here is to periodically poll the blog and determine whether there are any HTTP errors returned. If an error is returned, we simply restart apache and send an email off to ourselves notifying us of the action.

There are native Linux commands that could be compiled into a bash script to do all of this. But since I'm a windows programmer, it's way easier writing a simple .NET console application to do the work. In my implementation, I only need to know if the blog returns anything other than the requested page and a 200 response code. More...

With the Website Template in Visual Studio, all classes in the App_Code directory of your web site is compiled into a temporary assembly of its own when the web app is loaded by IIS. In order to get a handle to the assembly, you can use the following code snippet:

Assembly a = Assembly.Load("__code");

Of course, in Mono it doesn't work that way. To get the temporary compiled assembly you need to use the following:

Assembly a = Assembly.Load("App_Code");

Note that like everything on Linux, the casing matters here!  "app_code" will not work, unless you're running XSP on Windows.

Strangely enough the Mono implementation makes more sense. I couldn't find any information on the interwebs about this issue, so I eventually got it by guessing the correct name!

Not being able to trace through your code while doing a Mono port of an ASP.NET application can seriously hamper productivity. Until the Mono debugger is finally ready for prime time, we'll have to debug the old-school way.

One easy way of getting debug output from a Mono application is to simply use Console.WriteLine. If you're running your ASP.NET application through XSP2, the console output will be visible from the terminal that XSP was run in.

.NET supports using TraceListeners for capturing System.Configuration.Debug output. There is a handy ConsoleTraceListener that will convert all calls to Debug.WriteLine to console calls. This would be fantastic for Mono usage, but alas, Mono does not appear to support TraceListeners at all! My tests have shown that the overridden abstract methods in a TraceLister descendant are never called.

UPDATE: Seems my assumptions about TraceListeners not working in Mono was a bit premature, but not all that far off the mark.

As it turns out, TraceListeners do work, but only when you're running an application that has debugging enabled. This is the expected behaviour, and .NET follows the same guidelines.

However, when running a "Web Site" project (one that hasn't been pre-compiled), Mono still seems to have some issues. If you set the <compilation debug="true"> flag in the Web.config file, the application should be build with debug symbols and all debug output should function as expected. I've confirmed this to work on .NET, but am unable to get this working with XSP2 (Windows or Linux). The debug output does work however if you use a pre-compiled web site (i.e. ASP.NET Web Application in Visual Studio) compiled under the Debug configuration.

The Mono ASP.NET page suggests doing the following:

$ MONO_OPTIONS=--debug xsp2 
Listening on port: 8080 (non-secure) 
Listening on address: 0.0.0.0 
Root directory: /tmp/us 
Hit Return to stop the server.

 

This hasn't worked for me however. If anyone knows what I'm doing wrong here, please drop me a line and let me know!

I just came across the official mono porting ASP.NET applications guide. If you're planning on doing a port, I'd suggest you give this guide some attention.

The guide has some real gems like the following:

Using MONO_IOMAP

On Unix systems, Mono supports an I/O compatibility mode which allows you to ignore the file name case when accessing files on disk. The mode also takes care of disk designators (e.g. c:). Enabling the translation carries, obviously, some performance penalty, but is a good way to get your application up and running quickly. To enable the compatibility mode, make sure your web server's (XSP's or Apache's) environment contains the MONO_IOMAP variable set to all:

MONO_IOMAP=all export MONO_IOMAP

 

If you're using mod_mono, put the following line in your virtual host config file:

MonoSetEnv MONO_IOMAP=all

 

Knowing about this would have saved me a good couple of hours on the BlogEngine.NET port!

Something that will come in handy while porting applications to Mono is the ability to detect whether an application is running under Mono or .NET, and also whether it's running on Unix or Windows. While one would hope that .NET applications would be completely binary portable, there are still some situations where Mono's infancy becomes a stumbling block.

From the Mono Project Technical FAQ:

Having code that depends on the underlying runtime is considered to be bad coding style, but sometimes such code is necessary to work around runtime bugs.

The following methods are documented in the FAQ, but to save everyone time, I'll document them here.

Detecting Mono:

 1: using System;
 2:  
 3: class Program {
 4:  static void Main ()
 5:  {
 6:  Type t = Type.GetType ("Mono.Runtime");
 7:  if (t != null)
 8:  Console.WriteLine ("You are running with the Mono VM");
 9:  else
 10:  Console.WriteLine ("You are running something else");
 11:  }
 12: }

Detecting Linux/Unix:

 1: using System;
 2:  
 3: class Program {
 4:  
 5:  static void Main ()
 6:  {
 7:  int p = (int) Environment.OSVersion.Platform;
 8:  if ((p == 4) || (p == 128)) {
 9:  Console.WriteLine ("Running on Unix");
 10:  } else {
 11:  Console.WriteLine ("NOT running on Unix");
 12:  }
 13:  }
 14: }

I apologize for the bad code formatting above, but I'm still fighting to get proper syntax highlighting working with Live Writer and BlogEngine.NET.


I am a software developer / architect currently interested in combining .NET technologies with open-source operating systems. 

I am a member of the open-source BlogEngine.NET development team and focus mainly on ensuring Mono compatibility for the project.

twitter

BlogEngine.NET


At StayUnlimited Cape Town accommodation we help you choose from and book guest houses, self catering apartments, bed & breakfasts, luxury villas and hotel accommodation.