Wednesday, March 22, 2017

Getting .NET Core Web API to run on Ubuntu Raspberry Pi

These steps have been tested on a Raspberry Pi with Linux Ubuntu 16.04. The Web API project is created on Windows 10 machine.

Prepare Windows development machine

* Install Install .NET Core 2.0 SDK from https://github.com/dotnet/cli/tree/master
After installation check the version by running the following dotnet command in a Command Prompt.
dotnet --info
Output will be like:
.NET Command Line Tools (2.0.0-preview1-005448)

Product Information:
Version:            2.0.0-preview1-005448
Commit SHA-1 hash:  f8c3c4a030

Runtime Environment:
OS Name:     Windows
OS Version:  10.0.14393
OS Platform: Windows
RID:         win10-x64
Base Path:   C:\Program Files\dotnet\sdk\2.0.0-preview1-005448\

* Add development nuget sources by adding key values to the nuget.config. Nuget will now be able to get the latest packages that are under development:
Open C:\Users\xxxx\AppData\Roaming\NuGet\Nuget.config

add the keys:
<add key="aspnetcore-dev" value="https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json" />
<add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
<add key="dotnet-corefxlab" value="https://dotnet.myget.org/F/dotnet-corefxlab/api/v3/index.json" />
<add key="aspnetcore-ci-dev" value="https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json" />

Prepare Raspberry Pi

* Download Ubuntu Mate 16.04 from https://ubuntu-mate.org/raspberry-pi/ and install it on your Raspberry Pi.

* Install all of the required libraries for .NET Core:
sudo apt-get install libunwind8 libunwind8-dev gettext libicu-dev liblttng-ust-dev libcurl4-openssl-dev libssl-dev uuid-dev unzip

* Download and install .NET Core runtime components for Ubuntu 16.04 for ARM 32 (check: https://github.com/dotnet/core-setup#daily-builds). You should be able to do:
wget https://dotnetcli.blob.core.windows.net/dotnet/master/Binaries/Latest/dotnet-ubuntu.16.04-arm.latest.tar.gz
sudo mkdir -p /usr/share/dotnet
sudo tar -xvf dotnet-ubuntu.16.04-arm.latest.tar.gz -C /usr/share/dotnet/
sudo ln -sf /usr/share/dotnet/dotnet /usr/bin/dotnet

* determine dotnetcore runtime version by running command 'dotnet --info'
I my case it will show a version of 2.0.0-beta-001791-00
We will use this version information later on in the process.

* create directory ‘mywebapi’ in your home directory. In later step we will publish the files to this directory.

Create Web API Project on development machine

* create a .NET Core Web API project name ‘mywebapi’ by running command: dotnet new webapi -n mywebapi
Project file will look like:
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp1.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
  </ItemGroup>
</Project>

* Modify project file to:
- enable publishing for ubuntu 16.04. Add <RuntimeIdentifiers>ubuntu.16.04-arm</RuntimeIdentifiers>
- target .NET Core 2.0. Change TargetFramework into <TargetFramework>netcoreapp2.0</TargetFramework>
- make sure packages and publish will be for the .NET Core framework running on Raspberry Pi. In my case this was 2.0.0-beta-001791-00, so add node <RuntimeFrameworkVersion>2.0.0-beta-001791-00</RuntimeFrameworkVersion>
- add reference to make sure the libvu.so is being deployed. This was previously part of on of the standard Microsoft.AspNetCore package, however it was remove. So a reference to the libuv package. Add: <PackageReference Include="Libuv" Version="1.10.0-preview1-22036" />

The final project file:
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <RuntimeFrameworkVersion>2.0.0-beta-001791-00</RuntimeFrameworkVersion>
    <RuntimeIdentifiers>ubuntu.16.04-arm</RuntimeIdentifiers>
  </PropertyGroup>

  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
    <PackageReference Include="Libuv" Version="1.10.0-preview1-22036" />
  </ItemGroup>
</Project>

* Get the latest packages by using the dotnet restore command
dotnet restore

* Publish the Web API project for Ubuntu by using –r and the RuntimeIdentifier that was in the project file.
dotnet publish -r ubuntu.16.04-arm
This command published files to the \bin\Debug\netcoreapp2.0\ubuntu.16.04-arm\publish\ folder.

* copy files from build output (\bin\Debug\netcoreapp2.0\ubuntu.16.04-arm\publish) to the Raspberry Pi.
You can used pscp (that is available when Putty is installed). Open Command Prompt, go to \bin\Debug\netcoreapp2.0\ubuntu.16.04-arm\ folder. Run the following command to copy all files (including all (sub)directories) to the Raspberry Pi into the mywebapi directory.
pscp -l <raspberry-loginname> -scp -r publish <ip-address>:mywebapi

Start the Web API application on Raspberry Pi

* On Raspberry Pi go to the mywebapi directory. Run 'dotnet mywebapi.dll' to start the Web API application.
Output:
Hosting environment: Production
Content root path: /home/someusername/publish/publish
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

* To test the Web API service do a wget to ValuesController that is part of the sample Web API project.
wget http://localhost:5000/api/values

it will create a file values containing the response, in this case:
["value1","value2"]