Part 1: Hello, Linux

With all the excitement around Docker in Azure (and Windows Server 10!), I decided it was time to find out what all the fuss was about. My earliest forays were attempted using Vagrant on Windows, which creates Linux VMs using VirtualBox, but that was pretty painful. Every time I killed a VM, it would have to re-download or re-build all the Docker images. Also, running VMs on my Dell XPS13 Ultrabook was not the best performance experience ever.

So I bit the bullet and set up a Linux partition on my laptop. (ElementaryOS, if you're interested, and I like it a lot. Get the Freya beta release.) Which meant all of a sudden I was out of my Visual Studio comfort zone and up to my eyebrows in command lines, apt-get, Mono, OmniSharp, yo and other such exciting things.

Getting ASP.NET 5 up and running in this environment was not entirely straightforward, so in this post I'm going to try to retrace my steps and share what I had to do.

Installing Mono

For the best experience, you want the latest Mono. ElementaryOS Freya is
based on Ubuntu 14.04, which means you can add the Mono Project's package server to your apt sources and just install using apt-get. There's a step-by-step guide on the Mono website, but here are those steps for lazy people:

sudo apt-key adv --keyserver keyserver.ubuntu.com \
  --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
  
echo "deb http://download.mono-project.com/repo/debian wheezy main" | \
  sudo tee /etc/apt/sources.list.d/mono-xamarin.list
  
sudo apt-get update

sudo apt-get install mono-complete

If you're not familiar with Linux shells, the \ characters there are line continuations.

You used to have to import some certificates after doing this install, but the docs say you don't have to since 3.12. Just in case, that command was:

mozroots --import --sync

You can now write C# code, compile it with mcs and run it with mono, plus a bunch more besides. But that's not the point of this exercise...

Installing ASP.NET 5

I've found that a lot of things on Linux can be installed by curling a shell script from somewhere and piping it to sh, so it's nice to see that ASP.NET is playing nicely:

curl -sSL https://raw.githubusercontent.com/aspnet/Home/master/kvminstall.sh \
  | sh && source ~/.kre/kvm/kvm.sh

That installs everything. After that's finished, run kvm upgrade to install the latest K Runtime; then run kvm list and you should see:

Active Version              Runtime Location             Alias
------ -------              ------- --------             -----
  *    1.0.0-beta2          Mono    ~/.kre/packages      default

Which means you're all set.

Go on, write an MVC application.

This, of course, is not that simple. Even in this brave new world, an ASP.NET MVC application is a complicated thing, with a project.json and a Startup.cs and, of course, all the Controllers and Models and Views folders. The stuff that Visual Studio used to do for you when you went FILE > New Project.

It's called "scaffolding", and fortunately, there are command-line-friendly ways to do this sort of thing too. The one a lot of people are using these days is called yo, which is short for Yeoman (obviously it isn't, but whatever). It's a Node.js package, which means you install it using npm, except this is a new Linux install, which means you don't actually have Node installed. Shocking, I know. Python out-of-the-box, yes; Node, no.

Right, let's install Node, then:

curl -sL https://deb.nodesource.com/setup | sudo bash -
sudo apt-get install nodejs

We're nearly there, but the version of npm that comes with the Node install is ancient (1.4-ish), and yo wants an up-to-date one (>2.1). This stymied me for a few minutes, but it's actually easy to update npm using npm:

sudo npm update -g npm

Once that's done, you can install yo:

sudo npm install -g yo

Finally, we need to install a generator for yo. The OmniSharp guys have you covered:

sudo npm install -g generator-aspnet

Aaaaaand... we're done. We can finally create and run an ASP.NET MVC application on Linux.

(SPOILER: THIS IS NOT TRUE. SOMETHING IS GOING TO GO HORRIBLY WRONG. DO NOT WORRY. IT'S ALL PART OF THE INTRICATE STORY I AM WEAVING.)

All right, cd to whichever folder you put your projects under, and run

yo aspnet:app

And you get this:

     _-----_
    |       |    .--------------------------.
    |--(o)--|    |      Welcome to the      |
   `---------´   |   marvellous ASP.NET 5   |
    ( _´U`_ )    |        generator!        |
    /___A___\    '--------------------------'
     |  ~  |     
   __'.___.'__   
 ´   `  |° ´ Y ` 

? What type of application do you want to create? (Use arrow keys)
❯ Console Application 
  Web Application 
  MVC Application 
  Nancy ASP.NET Application 
  Class Library 
  Unit test project 

Which is completely brilliant. Use the cursor keys to select MVC Application, then enter a name when it asks for one, and it will generate an empty application for you:

? What type of application do you want to create? MVC Application
? What's the name of your ASP.NET application? Susan

     info ... Fetching https://github.com/OmniSharp/generator-aspnet/archive/release.tar.gz ...
     info This might take a few moments
......................
✔ Done in /home/mark/.cache/yeoman/OmniSharp/generator-aspnet/release

   create Susan/Controllers/HomeController.cs
   create Susan/Models/User.cs
   create Susan/Startup.cs
   create Susan/Views/Home/Index.cshtml
   create Susan/Views/Shared/_Layout.cshtml
   create Susan/project.json
   create Susan/wwwroot/.gitignore
/home/mark/.cache/yeoman


Your project is now created, you can use the following commands to get going
    kpm restore
    kpm build
    k run for console projects
    k kestrel or k webfor web projects

You'll want to cd into Susan (or whatever you've called your project) before running kpm restore, but when you do, the K package manager will go off to nuget.org and download all the packages needed to run the application.

Then you can just run k kestrel and... oh. Crap. That doesn't look good...

System.NullReferenceException: Object reference not set to an instance of an object
  at Microsoft.AspNet.Server.Kestrel.Networking.Libuv.loop_size () [0x00000] in <filename unknown>:0 
  at Microsoft.AspNet.Server.Kestrel.Networking.UvLoopHandle.Init (Microsoft.AspNet.Server.Kestrel.Networking.Libuv uv) [0x00000] in <filename unknown>:0 
  at Microsoft.AspNet.Server.Kestrel.KestrelThread.ThreadStart (System.Object parameter) [0x00000] in <filename unknown>:0

Aaaaaaargh.

What's gone on there? A quick search revealed an existing GitHub issue with the excellently informative name NullReferenceException when running Kestrel against vNext project on Ubuntu 14.04 LTS, in which it was revealed that the actual problem was that libuv, that stalwart of Nodey event loops, is not installed either. Kestrel is looking for a file on the shared library path called libuv.so.1 and it can't find it. Honestly, bloody Linux, seems like all you get out of the box is apt-get and tar. Oh, and Python.

So how do we install libuv then? That's right, FOSS fans: we build it from source.

apt-get -y install autoconf automake build-essential libtool

curl -L http://libuv.org/dist/v1.0.0/libuv-v1.0.0.tar.gz
tar xvf libuv-v1.0.0.tar.gz
rm libuv-v1.0.0.tar.gz
cd libuv-v1.0.0
sh ./autogen.sh
./configure
make
sudo make install
cd ..
rm -rf libuv-v1.0.0
sudo ldconfig

That ldconfig line at the end there is important, it updates some kind of thing somewhere that tells Linux what shared libraries it's got and where they are.

And now, after all of that, can you actually run k kestrel?

Yes. Yes, you can. It should just say:

Started

and you should be able to go to http://localhost:5004 and see the standard empty ASP.NET application home page. Yay!

Stopping Kestrel

If this were a Node application, you'd stop it by pressing Ctrl-C, but for some reason that hasn't been working for me. Seems like it's a known issue. I've been working around it by hitting Ctrl-Z to suspend the process, then killing the mono process:

[email protected]:~/asp/Susan$ k kestrel
Started

(Here's where I press Ctrl-Z)

[1]+  Stopped                 k kestrel
[email protected]:~/asp/Susan$ ps
  PID TTY          TIME CMD
 7428 pts/10   00:00:00 bash
 7769 pts/10   00:00:00 k
 7773 pts/10   00:00:00 klr
 7777 pts/10   00:00:01 mono
 7787 pts/10   00:00:00 ps
[email protected]:~/asp/Susan$ kill 7777
[email protected]:~/asp/Susan$ fg
k kestrel
/home/mark/.kre/packages/KRE-Mono.1.0.0-beta2/bin/klr: line 15:  7777 Terminated              mono $MONO_OPTIONS "$DIR/klr.mono.managed.dll" "[email protected]"
[email protected]:~/asp/Susan$ 

Anyway, the point is, it's all installed and it works and so in the next post, I'll show you how to set up SublimeText to work with ASP.NET and C#.