ASP .NET 5, Npgsql, Linux & Mono 4.2

Posted on Dec 9, 2015

Background

Logic Soft‘s primary application is a Windows based application written in C# using Windows.Forms. So when Microsoft announced ASP .NET 5 RC1, needless to say, we were quite excited.

We picked it up and started our experimentation - writing smaller applications and porting some of our side projects to the CoreCLR platform. As long as we didn’t go to the place that needed WIN32 APIs, it worked seamlessly.

With a small sum of experience, we took up the task of writing one of our internal dashboards with it. The aim was to be completely cross platform from the start since the it was to be hosted on our Linux server. The Dashboard is based on the completely revamped ASP MVC 6 with an Angular JS frontend. It uses Npgsql to connect to a PostgreSQL database at the backend.


The tl;dr version

  • Npgsql can’t work on Linux with CoreCLR RC1 because of issues - #874, #4631, #4652
  • Mono 4.2.1 is buggy. Pin version to 4.0.5 instead.
  • Pinning version to 4.0.5 on Ubuntu via suggested method results in Conflicting distribution issues when doing apt-get update. Pin it to 4.0.5.1 instead.

Npgsql on CoreCLR RC1

Because of how easy Visual Studio makes our work, we decided to write the app on windows but based on CoreCLR. After a few days of adding a major chunk of features, we decided to test the app out on Linux and instantly it failed with a TimeoutException when trying to open a connection to the Postgres DB.

System.TimeoutException: The operation has timed out.
at Npgsql.NpgsqlConnector.Connect(NpgsqlTimeout timeout)
at Npgsql.NpgsqlConnector.RawOpen(NpgsqlTimeout timeout)
at Npgsql.NpgsqlConnector.Open(NpgsqlTimeout timeout)
at Npgsql.NpgsqlConnector.Open()
at Npgsql.NpgsqlConnectorPool.GetPooledConnector(NpgsqlConnection Connection)
at Npgsql.NpgsqlConnectorPool.RequestConnector(NpgsqlConnection connection)
at Npgsql.NpgsqlConnection.OpenInternal(NpgsqlTimeout timeout)
at Npgsql.NpgsqlConnection.Open()

This didn’t make sense to me because when I used psql, I was able to connect to the Postgres DB. So I begun investigating.

My investigation led me to this issue filed on Npgsql’s repo. It talks about a problem with the Socket.Select method under Linux. The reporter of the issue opened an associated issue on the CoreFx repo which was very quickly fixed and merged in. The only nitpick of mine with this was that the fix would come through only in RC2. From the latest standup it was made clear that RC2 would not be released till Feb 2016. We wanted to get this dashboard into production by end of next week. This meant that I had to look for alternatives.

Enter Mono (4.2.1)

The alternative here is quite simple - Mono. From their site:

Sponsored by Xamarin, Mono is an open source implementation of Microsoft’s .NET Framework based on the ECMA standards for C# and the Common Language Runtime. A growing family of solutions and an active and enthusiastic contributing community is helping position Mono to become the leading choice for development of cross platform applications.

The first thing I did was to install the mono-complete package as advised on their very clear installation page. This installed Mono 4.2.1. Along with this I installed the associated dnx too.

Once this was done, I used yeoman and the omnisharp generators for ASP .NET 5 to generate a simple console application. I added Npgsql as a dependency and wrote just enough code to open a connection to the Postgres DB and when I ran it, I could connect to the DB with no TimeoutException biting my behind. I was happy. With this, my expectation was that I could just run a dnu restore on my project, and get cracking.

After running a dnu restore, I quickly ran dnx web to see the ever friendly Now listening on: http://localhost:5000 message greet me. With a great sum of enthusiasm, I visited http://localhost:5000 on my browser only to see it never finish. I switched back to the console to check and I saw that the request processing was stuck up at one stage:

> dnx web
Hosting environment: Production
Now listening on: http://*:5004
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNet.Hosting.Internal.HostingEngine[1]
      Request starting HTTP/1.1 GET http://localhost:5004/  
info: Microsoft.AspNet.Mvc.Controllers.ControllerActionInvoker[1]
      Executing action method MvcSample.Web.HomeController.Index with arguments () - ModelState is Valid'

No matter how long I’d let it be, the response wouldn’t come through. Roadblock.

After a while of fiddling with DNX by setting DNX_TRACE=1, I decided that the best way of understanding better would be to run a “Microsoft certified” basic application. These can be found for over on the home repo under the aspnet organization. Here, in the samples directory one can find applications for each of the releases Microsoft has made. All the way from -beta4 to -RC1-update1 to the cutting edge one as well. This would be a good place for me to start debugging the issue I was facing, I thought.

Once I cloned the repo, I went into the 1.0.0-rc1-update1/HelloMvc folder and did a dnu restore to bring down dependencies. Post this, I ran dnx web and navigated to the URL. To my surprise I again hit the same problem. It was getting stuck at precisely the same place as earlier:

> dnx web
Hosting environment: Production
Now listening on: http://*:5004
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNet.Hosting.Internal.HostingEngine[1]
      Request starting HTTP/1.1 GET http://localhost:5004/  
info: Microsoft.AspNet.Mvc.Controllers.ControllerActionInvoker[1]
      Executing action method MvcSample.Web.HomeController.Index with arguments () - ModelState is Valid'

Initially, I was quite skeptical of myself and was convinced that I was doing something wrong. So I double checked everything again - dnx, dnu and dnvm versions. I reinstalled everything and tried again but alas - Same issue.

With nothing else possible, I opened an issue on the aspnet/home repo: #1161 detailing all the steps that I followed and the problem that I was facing. Following this, I jumped on to the JabbR chat room to see if I could find anyone. I posted about the issue there as well and one of the core guys at Microsoft - David Fowler asked me to try out Mono 4.0.5 instead of 4.2.1. He went on to mention that 4.2.1 was filled with quite a few bugs and the recommendation is to pin the version to 4.0.5 until the bugs in 4.2.1 were fixed.

Exit Mono (4.2.1)

Now, on my Ubuntu box, I had 4.2.1 installed which I now had to uninstall in order to replace it with 4.0.5. As with uninstalling any other package, I followed the usual steps:

sudo apt-get remove mono-complete
sudo apt-get purge mono-complete
sudo apt-get autoremove

Enter Mono (4.0.5?)

The Mono install page has a section on how to access older releases which was the one I followed in order to pin my Mono version to 4.0.5. I edited the /etc/apt/sources.list.d/mono-xamarin.d and changed the line to

deb http://download.mono-project.com/repo/debian wheezy/snapshots/4.0.5 main

Following this I did a sudo apt-get update to bring update the package listing and soon enough ended up with this:

W: Conflicting distribution: http://download.mono-project.com wheezy/snapshots/4.0.5 InRelease (expected wheezy/snapshots but got wheezy)

After some (rather hard) googling, I came across this issue filed on Xamarin’s bugzilla. However this was for installing the 3.12.0 version and a workaround was suggested to suffix a /. to the end of the version. I then updated the mono-xamarin.d file to have

deb http://download.mono-project.com/repo/debian wheezy/snapshots/4.0.5/. main

instead but to no avail. I ended up with the same error message again.

After some digging around on Mono’s download server for 4.0.5, I noticed that the InRelease file for 4.0.5 had the Suite listed as 4.0.5.1. Off a whim, I tried replacing 4.0.5 with 4.0.5.1 in my mono-xamarin.d file.

deb http://download.mono-project.com/repo/debian wheezy/snapshots/4.0.5.1/. main

Running sudo apt-get update post this didn’t leave me with the dreaded “Conflicting distribution” error anymore. After this I just installed the mono-complete package as before.


Note: The first time I did this, somehow mono-runtime didn’t get removed and I was having package clash problems when trying to install the mono-complete package after pinning 4.0.5.1 (since the mono-runtime for 4.2.1 was still installed). I had to explicitly remove the mono-runtime package for it to work.


With mono 4.0.5 installed, I got back to my project and booted it up again with dnx web. I visited the URL and finally

> dnx web
Hosting environment: DEVELOPMENT
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNet.Hosting.Internal.HostingEngine[1]
      Request starting HTTP/1.1 GET http://localhost:5000/  
info: Microsoft.AspNet.Mvc.Controllers.ControllerActionInvoker[1]
      Executing action method SessyDash.Controllers.HomeController.Index with arguments () - ModelState is Valid'
info: Microsoft.AspNet.Mvc.ViewFeatures.ViewResultExecutor[1]
      Executing ViewResult, running view at path /Views/Home/Index.cshtml.
info: Microsoft.Extensions.DependencyInjection.DataProtectionServices[0]
      User profile is available. Using '/home/shrayasr/.local/share/ASP.NET/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
info: Microsoft.AspNet.Mvc.Infrastructure.MvcRouteHandler[2]
      Executed action SessyDash.Controllers.HomeController.Index in 0.4223ms
info: Microsoft.AspNet.Hosting.Internal.HostingEngine[2]
      Request finished in 0.468ms 200 text/html; charset=utf-8

The page rendered successfully and all the connections to the PostgreSQL DB went through as well. Success!

Conclusion

This meant that the set of features that we had written for the dashboard now worked on both Windows (via CoreCLR) and on Linux (via Mono). This is really exciting for us as a team since we’ve only worked on the Windows platform for so long. Being able to translate those skills (almost) directly to other platforms with Microsoft’s support is a very very big win.

ASP .NET 5 is a really interesting platform to work on. It feels like Microsoft is taking a wonderful way forward. Personally I’ve always enjoyed programming with C# and this just makes that experience that much better.

However, this being still a nacent platform, has a few rough edges and adopting into it this early has its own set of problems related to documentation and finding workarounds. But the dynamic team at Microsoft really eases that out too. The JabbR room seems like a very interesting place to be on and I intend to be a frequent visitor there helping people and seeking help too in the future.

Heres to more adventures with CoreCLR, ASP .NET 5 et al. Cheers!