/ .NET

ASP.NET Core debugging tips for Visual Studio Code

These days I run a Windows laptop with Visual Studio on it, but at home I
still have a great Mac Machine purring away in my home office. I like that
machine since it has a huge display (27 inches) and I find Mac OS still better
to use then Windows.

From time to time I like to work on a side project on my Mac. These days I'm
building a small web application to keep track of session proposals I sent out.
I'm building this using ASP.NET Core and Visual Studio Code.

Visual Studio Code is a great editor for writing .NET core code in C#
or F# for that matter. There are however a few little things that trip me up
every time I try to debug my code.

Setting up your project for debugging

When you open a .NET Core project in Visual Studio Code, the editor will suggest
you add configuration to run the project from the editor. I usually click yes to
get it out of the way.

The editor will generate a launch.json file in the .vscode folder.
This file contains the settings for Visual Studio Code that it needs to start
your project in the debugger.

    "version": "0.2.0",
    "configurations": [
            "name": ".NET Core Launch (web)",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build",
            "program": "${workspaceRoot}/src/Proposalkeeper/bin/Debug/netcoreapp1.0/Proposalkeeper.dll",
            "args": [],
            "cwd": "${workspaceRoot}",
            "stopAtEntry": false,
            "internalConsoleOptions": "openOnSessionStart",
            "launchBrowser": {
                "enabled": true,
                "args": "${auto-detect-url}",
                "windows": {
                    "command": "cmd.exe",
                    "args": "/C start ${auto-detect-url}"
                "osx": {
                    "command": "open"
                "linux": {
                    "command": "xdg-open"
            "env": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            "sourceFileMap": {
                "/Views": "${workspaceRoot}/Views"
            "name": ".NET Core Attach",
            "type": "coreclr",
            "request": "attach",
            "processId": "${command.pickProcess}"

It's mostly stuff that Visual Studio Code needs, but there is one important setting
that I need to point out here.

If you have a solution that has several subfolders for projects you will find
that the launch configuration doesn't work the way you expect it to.

My solution layout is like this:

|-- src
  |-- Proposalkeeper
    |-- Views
    |-- Controllers
    |-- Models
    |-- Data
|-- test
  |-- Proposalkeeper.UnitTests

In order for my app to run correctly I need to navigate to the src/Proposalkeeper
folder and execute dotnet run there. This is required since it will lookup the
views folder relative to the current working folder.

When you start the application from Visual Studio Code without modifying the file
ASP.NET Core web applications will be unable to find the views in your web app.

When you open the root of your solution, Visual Studio Code assumes that the workspace
root and thus the cwd setting for debugging is the root of your solution.
Now when you start to debug it will load your application code from the subfolder
src/SomeApp with the solution root as its working folder. Your application code
will then try to find views in ${workspaceroot}/Views where of course it can't find

In order to make things work correctly you need to modify the cwd setting to point
to the correct folder where your ASP.NET core project is located.

Now you can press F5 and Visual Studio Code will correctly start the application.

Debugging Symbols

The launch configuration is one thing that tripped me up, here's another. When I was
able to run my application I was unable to actually break on a line because the debugger
didn't load any debug symbols for my application.

The default setup of an ASP.NET Core application that is generated using Yeoman
doesn't have debug symbols enabled. You need to explicitly enables this in
your project.json file.

"buildOptions": {
  "debugType": "portable",
  "emitEntryPoint": true,
  "preserveCompilationContext": true

Add the debugType setting and make sure that it is set to portable. This will
generate a PDB file in the output folder of the project so that the debugger
is able to break on breakpoints you configure.