Requirements

  • Visual Studio 2015
  • cmd
  • PowerShell
  • Raspberry PI with Windows 10 IoT on local network

Note: All instructions concern the development machine unless otherwise noted.

Connecting the development machine to Windows 10 IoT

To start a remote session on the Pi in PowerShell, execute the following command:

Enter-PSSession -ComputerName <address> -Credential <address>\Administrator

Where <address> is the local network address of the Pi. If you gave the device a unique name, you can use that name instead of the address. You will be prompted for the device password you set earlier, and then PowerShell will connect and allow you to remotely execute commands.

Installing DNVM (DotNet Version Manager) and dnx runtimes

On the development machine, open PowerShell and run the following command:

-NoProfile -ExecutionPolicy unrestricted -Command "&{$Branch='dev';iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.ps1'))}"

After dnvm is installed, open the Windows command prompt and run the following commands:

dnvm update-self
set DNX_UNSTABLE_FEED=https://www.myget.org/F/aspnetmaster/api/v2
dnvm install latest -r coreclr -arch x86 -u
dnvm install latest -r coreclr -arch x64 -u
dnvm install latest -r clr -arch x86 -u
dnvm install latest -r clr -arch x64 –u
dnvm install latest -r coreclr -arch ARM -u

This installs versions of the dnx runtimes for all the available Windows architectures.

The relevant runtime for development will be dnx-coreclr-win-x86/x64, and the relevant runtime for the Raspberry Pi will be dnx-coreclr-win-arm.

Due to instability in the latest versions of the runtime, we will install and consistently and use only the 1.0.0-rc1-final versions of the runtimes and packages. These come from aspnetmaster instead of the default unstable feed.

Creating the web application

Open Visual Studio 2015 and open a new project. Choose the "ASP.NET Web Application" template under Templates > Visual C# > Web.

In the following dialog, choose the “Empty” ASP.NET 5 template and create the project.

This will create a project with a Startup.cs and a few JSON configuration files. You can delete Project_Readme.html.

Open global.json and replace its contents with the following:

{
  "projects": [ "src" ],
  "sdk": {
    "version": "1.0.0-rc1-final"
  }
}

Including the dependencies

Open the Tools menu and navigate to NuGet Package Manager > Package Manager Settings. In the dialog, switch to the Package Sources view. Use the + icon to add a new package source, and change the configuration to the following:

Name: rc1 Stable vNext
Source: https://www.myget.org/F/aspnetmaster/api/v2

Click OK to save the configuration.

If the + icon is not active, you may need to delete NuGet.Config from AppData\Roaming\NuGet.

Open project.json. Replace the dependencies section with the following:

"dependencies": {
    "Microsoft.AspNet.Diagnostics": "1.0.0-rc1-final",
    "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
    "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
    "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-final",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
    "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final",
    "Microsoft.AspNet.Tooling.Razor": "1.0.0-rc1-final",
    "Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final"
  },

When you save the file, you will notice a "Restoring packages…" message appear in the Solution Explorer. When project.json is modified with new dependencies, the packages are installed or fetched from an existing local installation by NuGet using the package sources you configured.

If other packages are needed, ensure that you reference and install the rc1-final version.

Configuring the application for self-hosting with Kestrel during development

Use the run dropdown to select "web" for the debug configuration.

Next, open the project properties page and enter the Debug tab. Check "Use Specific Runtime" and change the platform to ".NET Core."


Save these settings. Now, when you F5 and begin debugging, Kestrel will run to host your application.

To control which port Kestrel listens on, and to allow connecting to it on the Raspberry Pi instead of localhost, we will create a file in the project root called hosting.json and use the following for its contents:

{
"server": "Microsoft.AspNet.Server.Kestrel",
"server.urls": "http://*:5005/"
}

You may use another valid port, or specify multiple URLs like so:

  "server.urls": "http://*:5005/;https://*:5006"

In production, the * may be replaced with an IP address or domain name as appropriate.

After saving the configuration, open the project properties again, check "Launch URL" and enter the same localhost address as Kestrel listens on (for example, http://localhost:5005). Now when the project is started with F5, the application will open in the browser automatically.

Using MVC 6 in the application

We already added the dependencies for MVC 6. Now, we'll use Startup.cs to configure MVC in the application. Replace the file's using statements with the following:

using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Extensions.DependencyInjection;

In the ConfigureServices method, add the following:

services.AddMvc();

Replace the body of the Configure method with the following:

app.UseDeveloperExceptionPage(); 
app.UseIISPlatformHandler(); 
app.UseStaticFiles(); 
app.UseMvc(routes => {    
routes.MapRoute(name: "default",         
  template: "{controller=Home}/{action=Index}"     
); 

The application is now configured to use standard MVC features. In production, you will want to replace UseDeveloperExceptionPage with a proper production exception handling strategy.

Publishing/packaging the web application

To package the application for local deployment and testing, you can use Visual Studio's usual publish workflow. To package with the ARM runtime, which is needed for deployment on the Raspberry Pi, you must use the command line.

Publish for local:

In the Publish dialog's Profile tab, choose "File System" as the target. In the Settings tab, ensure "Compile source files into NuGet packages" is checked under File Publish Optons. For the Target DNX Version, choose dnx-coreclr-win-x86-1.0.0-rc1-final.

Publish for Raspberry Pi:

Navigate to the project root in the Windows file explorer (the location of the xproj and project.json files). Hold Shift and right-click in the folder, and select "Open command window here" from the context menu. Enter the following command in the command prompt:

dnu publish --out <destination> --no-source --runtime dnx-coreclr-win-arm.1.0.0-rc1-final

Where <destination> is the directory path to publish to. Execute this command to build and publish the application.

Important: There is an error in the build process for arm.1.0.0-rc1 that causes a number of necessary runtime binaries to not be built or copied properly. These binaries, built with a (luckily) compatible rc2 runtime, must be copied over manually.

You can find a ZIP download with the missing binaries here.

Copy the DLLs from the ZIP to the following bin folder under your published application's approot, skipping any already existing files:

Running/deploying the packaged application

The application will be published with a structure of three folders: approot, logs, and wwwroot. In approot is web.cmd, which will run Kestrel and start listening when executed.

Use an FTP client or PowerShell to copy these folders to the Raspberry Pi's user documents folders. Next, with PowerShell connected to the Pi, run the following command:

netsh advfirewall firewall add rule name="Allow DNX Port <port>" dir=in action=allow protocol=TCP localport=<port>

Where <port> is the port number your application was configured to listen on (for example, 5005). This will make the Windows 10 IoT firewall allow incoming requests to the application. Next, navigate in PowerShell to the approot folder on the Pi. Run web.cmd with the following command:

.\web.cmd

Kestrel will start running. If you receive an error message about coreclr.dll, follow the instructions above marked Important. If you receive an error message about libuv.dll (see below screenshot), you will need to add a location to the environment path where the DLL can be found. You can place the DLL in a common location and permanently add that location to the path, or temporarily set the path to include the location already in your published project; for example:

$env:Path += ";<application>\approot\packages\Microsoft.AspNet.Server.Kestrel\1.0.0-rc1-final\runtimes\win10-arm\native"

Where <application> is the full path to your application directory. After adding to the path, run web.cmd again.

When Kestrel is successfully started, you can now access the application through the Pi's local network address (or machine name) at the configured port.