Search by Tags

.NET Core Development and Debugging on Torizon Using Visual Studio Code

 
Applicable for

Article updated at 05 Jun 2019
Subscribe for this article updates

Introduction

Those instructions have been tested on Linux (Ubuntu 18.04) and Windows 10.

On Windows 10 you need to perform some extra configuration steps to allow the required tools to work, those Windows-specific steps will be described in the instructions when required.

If you are not familiar about the conventions we use in the documentation, please check our online reference.

GitHub Repository

You will find back-up material for this article, as well as additional samples and other resources in the dot-net-core repository on Toradex GitHub.

Prerequisites

You need to install the following applications on your development machine:

Windows 10

On Windows you also have to enable the Windows Subsystem for Linux, you can follow instructions provided by Microsoft.

Configure the Target Device

On the target device you should just install a Torizon image with Docker support. Your device must be connected to the local network.

Since many commands are executing over SSH, it may be a good idea to enable passwordless SSH connection to the target, so you don't have to input a password at every connection. Remember that the default password for the torizon user is "torizon".

Create a New Dotnet Core Project

To create a new project you should have the dot net core SDK v 3.0 installed on your development machine and dotnet (dotnet.exe on Windows 10) in your system path.

Open a terminal/command prompt, create a new folder, cd into it and create a new dotnet application.

$ mkdir mytestapp
$ cd mytestapp
$ dotnet new console
$ code .

This will create a new .NET Core application and start Visual Studio Code in that same folder.

Copy content of the template folder in this repository to the .vscode subfolder of your project, this will add all the scripts and configuration files required to build, deploy and debug your .NET application on Torizon.

Configure Visual Studio Code

First time you open a .NET/C# project in Visual Studio Code may take a few minutes because the editor will download all required extension, libraries and componets.

Then you should be able to browse the contents of your folder.

Open the file named settings.json in the .vscode folder and change configuration parameters according to your application and device settings:

.vscode/settings.json
{
    "toradexdotnetcore.targetSSHPort": "8023",
    "toradexdotnetcore.targetDevice": "192.168.1.114",
    "toradexdotnetcore.SSHkey": "../containers/dotnetcoredbg/id_rsa",
    "toradexdotnetcore.containersTemplatePath": "../containers",
    "toradexdotnetcore.maindll": "dotnetcoreapp.dll",
    "toradexdotnetcore.prjname": "dotnetcoreapp.csproj",
    "toradexdotnetcore.containerParms": "",
    "toradexdotnetcore.containerParms.debug": "",
    "toradexdotnetcore.containerParms.release": "",
    "toradexdotnetcore.containerTemplate.debug": "dotnetcoredbg",
    "toradexdotnetcore.containerTemplate.release": "dotnetcore"
}

Of course replace 192.168.114 with the IP address of your target device and dotnetcoreapp.* with the name of your current project. You will also need to build some containers (process is described in next chapter, if you keep the containers folder from this repo in the parent folder of your dot net core app you can leave the path in containerTemplatePath as it is, otherwise you should point it to the right folder).

You will have also a task configuration file (tasks.json) and a debug configuration file (launch.json). You may need to change those files if you need to deploy or debug your application in a custom way, but the files provided in this article should work for most of the applications:

tasks.json
launch.json

After you made the changes you shoud close and re-open Visual Studio Code to ensure that the new configuration settings are applied.

Build and Deploy the Debug Container

Before you can start developing and debugging your application you should build the container that will be used to run and debug it.

To build the container, perform following steps:

  • Press ctrl+P to open the command palette
  • Type task builddebugcontainer and press enter
  • Build will start, it may take a few minutes and at the end you should see the following message:

    Successfully built XXXXXXXX
    Successfully tagged dotnetcoredbg:latest
    
  • Press ctrl+P again to re-open command palette

  • Type task deploydebugcontainer and press enter
  • The system will re-run build (it will be very fast, because container image is alread up to date after previous step) and then deploy the container to the target device. This will be done over local network and should take a couple of minutes.
  • If the deployment has been successful you should see the following message (the first sentence will appear only if you already deployed the container to that device in the past):

    > Executing task: docker save dotnetcoredbg:latest | ssh torizon@192.168.1.114 'docker load' <
    
    The image dotnetcoredbg:latest already exists, renaming the old one with ID sha256:c0c31bd58adc9cb8e3ee69425b620b29e699a59151ce6689fe09d604a825868b to empty string
    Loaded image: dotnetcoredbg:latest
    

Once you deployed the container for the first time, you will probably not need to do it again because the application and all its dependencies will be kept separated from the container used for debugging, this will make debug-fix-debug cycle much faster.

Build and Run Your Application

To run your application on the target check that the ".NET Core Launch (console)" entry is selected in the debug window and press F5 to start debugging.

Visual Studio Code will build, publish and deploy your application to the target, restart debug container (to ensure that execution behaviour won't be influenced by previous runs) and start your application, breaking on the opening brace of your Main function.

This is the typical output of a debug session:

Debug session output

Message "Error response from daemon: No such container: dotnetcoreapp-dbg" will appear if the debug container was not already running, this is normal and will happen the first time you start a debug session after device boot.

You can use F10 to step over instruction, F11 to step into and all the other debugging features provided by Visual Studio Code C# debugger.

Package and Deploy Your Application

When you are happy about your application and want to run it directly on a Torizon device you will have to build a release container that will include the dotnet core runtime, your application and all its dependencies. To do this:

  • press ctrl+P to open command palette
  • type task buildreleasecontainer to start build.
  • Your application will be built and published and then build of the release container image will start.
  • build should complete successfully

    Successfully built XXXXXXXXX
    Successfully tagged dotnetcore-YYYYYYYY:latest
    
  • The new image tag will be "dotnetcore-" and the name of your application folder, you will be able to change that by running docker build with a different tag (see chapter "customizing containers").

  • press ctrl+P again to re-open the command palette.
  • type task runreleasecontainer to deploy and run your container on the device. The output from this command should be similar as the one presented below for reference:

    Deploy and run container output

ASP.NET Core Application

Building and debugging an ASP.NET Core application is very similar to the process described in the previous chapters for .NET core applications.

You can use dotnet new command to create different kind of ASP.NET core application, depending on what kind of framework and model you want to use.

In this document we will describe creation of a basic application with HTTP only interface, adding HTTPS involves certificate management and this can be done in different ways using different kind of certificates, depending on specific application needs.

You should add an additional setting to .vscode/settings.json to set the port that will be used to expose the HTTP server.

.vscode/settings.json
{
    "toradexdotnetcore.targetHTTPPort": "5000",
    "toradexdotnetcore.targetSSHPort": "8022",
    "toradexdotnetcore.targetDevice": "192.168.1.114",
    "toradexdotnetcore.SSHkey": "../containers/aspdotnetcoredbg/id_rsa",
    "toradexdotnetcore.containersTemplatePath": "../containers",
    "toradexdotnetcore.maindll": "aspdotnetcoreapp.dll",
    "toradexdotnetcore.prjname": "aspdotnetcoreapp.csproj",
    "toradexdotnetcore.containerParms": "-p ${config:toradexdotnetcore.targetHTTPPort}:${config:toradexdotnetcore.targetHTTPPort}",
    "toradexdotnetcore.containerParms.debug": "",
    "toradexdotnetcore.containerParms.release": "",
    "toradexdotnetcore.containerTemplate.debug": "aspdotnetcoredbg",
    "toradexdotnetcore.containerTemplate.release": "aspdotnetcore"
}

You should then build and deploy the debug container as described in previous chapter (ASP.NET Core uses a different base container) and change the application code to use the native (kestrel) http server on the port you configured.

  • open Program.cs in the Visual Studio Code editor
  • add the following code to the CreateHostBuilder function (here we use port 5000, as we did in the setting.json sample above):

    Program.cs (function CreateHostBuilder)
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>().ConfigureKestrel((context, options) =>
                    {
                        options.Listen(IPAddress.Any, 5000);
                    });
                });
    

You can then press F5 and start debugging your application.

Debugger won't stop on the entry point (this is not usually very useful for applications that receive requests from clients and just perform basic initialization at startup), but you can place breakpoints in your code as usual.

Customize Containers

.NET Core applications will not run directly on Torizon, they will be hosted inside a container.

Microsoft provides base containers for .NET Core and ASP.NET Core applications, those need some customization to provide debugging capabilities and to host your application directly inside the container for release builds.

Inside this repo you will find a folder named "containers", inside the folder you will find four different subfolders:

  • dotnetcore: This is the basic release container for .NET Core application, it will just integrate your application inside a container and run it when that same container is started. Each application will have a different container named dotnetcode-\.

  • dotnetcoredbg: This is a generic "host" container providing support (via SSH on port 22) to run and debug .NET core applications. It integrates visual studio debugger and SSH server.

  • aspnetcore: This is release container for ASP.NET Core applications, it includes the runtime, adds the application and runs it at startup, its behaviour is very similar to dotnetcore container, but it's based on a different Microsof-provided base image and exposes also port 5000 for the HTTP interface. You may need to change that or add additional ports that your application may need.

  • aspnetcoredbg: This is the ASP.NET version of dotnetcoredbg container, you may need to change it if you plan to expose different or additional ports.

Those containers can be customized by changing their Dockerfile or by creating a new Dockerfile that uses them in their "FROM" statement.

The container name should match the folder name, and custom names may be configured in settings.json for your specific project.

You can add additional exposed port using the EXPOSE clause (this is needed for server ports, not for ports your application accesses as a client) or add additional os components needed by your application.

Microsoft-provided containers are based on debian stretch, so you can add components invoking the apt package manager.

If you just need to specify different parameters at runtime (mapping ports or folders, sharing devices, running container in privileged mode or with a different user account) you can do that using toradexdotnetcode.containerParms or toradexdotnetcode.containerParms.debug/release if those parameters are required only for a specific configuration.