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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{
"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:

1
2
3
4
5
6
7
8
|-- 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 them.

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.

1
2
3
4
5
"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.

Enjoy!