Skip to content

Debug and Launch Dapr Applications in VSCode

This page shows you how to configure VSCode to run and debug multiple Dapr applications at same time.

Debug and launch Dapr applications in VSCode

We need to update VS code tasks.json and launch.json configuration files included in your workspace. Once completed you should be able to use the Run and Debug button on the activity bar within VS Code to launch all services to be able to debug them locally.

First we need to add a new launch configuration for the Backend Web API and Frontend Web App projects. To accomplish this, open file launch.json and add the two configurations shown below.

Note

Make sure you append the configurations below to the existing array instead of replacing what you have. This way you will preserve your existing configuration and simply add two new ones.

Looking for complete launch.json?
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch (web app)",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build-backend-api",
            "program": "${workspaceFolder}/TasksTracker.WebPortal.Frontend.Ui/bin/Debug/net6.0/TasksTracker.WebPortal.Frontend.Ui.dll",
            "args": [],
            "cwd": "${workspaceFolder}/TasksTracker.WebPortal.Frontend.Ui",
            "stopAtEntry": false,
            "serverReadyAction": {
                "action": "openExternally",
                "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
            },
            "env": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            },
            "sourceFileMap": {
                "/Views": "${workspaceFolder}/Views"
            }
        },
        {
            "name": "Launch (backend api)",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build-webapp-ui",
            "program": "${workspaceFolder}/TasksTracker.TasksManager.Backend.Api/bin/Debug/net6.0/TasksTracker.TasksManager.Backend.Api.dll",
            "args": [],
            "cwd": "${workspaceFolder}/TasksTracker.TasksManager.Backend.Api",
            "stopAtEntry": false,
            "serverReadyAction": {
                "action": "openExternally",
                "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
            },
            "env": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            },
            "sourceFileMap": {
                "/Views": "${workspaceFolder}/Views"
            }
        },
        {
            "name": "Launch (background processor)",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build-processor-svc",
            "program": "${workspaceFolder}/TasksTracker.Processor.Backend.Svc/bin/Debug/net6.0/TasksTracker.Processor.Backend.Svc.dll",
            "args": [],
            "cwd": "${workspaceFolder}/TasksTracker.Processor.Backend.Svc",
            "stopAtEntry": false,
            "serverReadyAction": {
                "action": "openExternally",
                "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
            },
            "env": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            },
            "sourceFileMap": {
                "/Views": "${workspaceFolder}/Views"
            }
        },
        {
            "name": ".NET Core Attach",
            "type": "coreclr",
            "request": "attach"
        },
        {
            "name": "Launch (backend api) with Dapr",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "backend-api-dapr-debug",
            "program": "${workspaceFolder}/TasksTracker.TasksManager.Backend.Api/bin/Debug/net6.0/TasksTracker.TasksManager.Backend.Api.dll",
            "args": [],
            "cwd": "${workspaceFolder}/TasksTracker.TasksManager.Backend.Api",
            "stopAtEntry": false,
            "serverReadyAction": {
                "action": "openExternally",
                "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
            },
            "env": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            },
            "sourceFileMap": {
                "/Views": "${workspaceFolder}/Views"
            },
            "postDebugTask": "daprd-down-backend-api"
        },
        {
            "name": "Launch (web app) with Dapr",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "webapp-ui-dapr-debug",
            "program": "${workspaceFolder}/TasksTracker.WebPortal.Frontend.Ui/bin/Debug/net6.0/TasksTracker.WebPortal.Frontend.Ui.dll",
            "args": [],
            "cwd": "${workspaceFolder}/TasksTracker.WebPortal.Frontend.Ui",
            "stopAtEntry": false,
            "serverReadyAction": {
                "action": "openExternally",
                "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
            },
            "env": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            },
            "sourceFileMap": {
                "/Views": "${workspaceFolder}/Views"
            },
            "postDebugTask": "webapp-ui-daprd-down"
        },
        {
            "name": "Launch (background processor) with Dapr",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "processor-svc-dapr-debug",
            "program": "${workspaceFolder}/TasksTracker.Processor.Backend.Svc/bin/Debug/net6.0/TasksTracker.Processor.Backend.Svc.dll",
            "args": [],
            "cwd": "${workspaceFolder}/TasksTracker.Processor.Backend.Svc",
            "stopAtEntry": false,
            "serverReadyAction": {
                "action": "openExternally",
                "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
            },
            "env": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            },
            "sourceFileMap": {
                "/Views": "${workspaceFolder}/Views"
            },
            "postDebugTask": "processor-svc-daprd-down"
        }
    ],
    "compounds": [
        {
            "name": "RunAll",
            "configurations": ["Launch (web app)", "Launch (backend api)", "Launch (background processor)",],
            "stopAll": true
        },
        {
            "name": "RunAll with Dapr",
            "configurations": [ "Launch (backend api) with Dapr", "Launch (web app) with Dapr", "Launch (background processor) with Dapr", ],
            "stopAll": true
        }
    ]
}

Note

The configuration below assumes that you are using .net 6. If you are using a different .net version make sure you update the paths to use the correct version. For example if using .net 7 then change the path to say net7.0 instead of net6.0.

{"configurations":
[
  {
    "name": "Launch (backend api) with Dapr",
    "type": "coreclr",
    "request": "launch",
    "preLaunchTask": "backend-api-dapr-debug",
    "program": "${workspaceFolder}/TasksTracker.TasksManager.Backend.Api/bin/Debug/net6.0/TasksTracker.TasksManager.Backend.Api.dll",
    "args": [],
    "cwd": "${workspaceFolder}/TasksTracker.TasksManager.Backend.Api",
    "stopAtEntry": false,
    "serverReadyAction": {
      "action": "openExternally",
      "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
    },
    "env": {
      "ASPNETCORE_ENVIRONMENT": "Development"
    },
    "sourceFileMap": {
      "/Views": "${workspaceFolder}/Views"
    },
    "postDebugTask": "daprd-down-backend-api"
  },
  {
    "name": "Launch (web app) with Dapr",
    "type": "coreclr",
    "request": "launch",
    "preLaunchTask": "webapp-ui-dapr-debug",
    "program": "${workspaceFolder}/TasksTracker.WebPortal.Frontend.Ui/bin/Debug/net6.0/TasksTracker.WebPortal.Frontend.Ui.dll",
    "args": [],
    "cwd": "${workspaceFolder}/TasksTracker.WebPortal.Frontend.Ui",
    "stopAtEntry": false,
    "serverReadyAction": {
      "action": "openExternally",
      "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
    },
    "env": {
      "ASPNETCORE_ENVIRONMENT": "Development"
    },
    "sourceFileMap": {
      "/Views": "${workspaceFolder}/Views"
    },
    "postDebugTask": "webapp-ui-daprd-down"
  }
]}

Note

We have a preLaunchTask and a postDebugTask which we need to define right now. Those tasks are Dapr tasks.

The Dapr VSCode extension we have previously installed helps us to define those pre- and post-debug tasks.

To accomplish this, open the file tasks.json and click Ctrl+Shift+P, and type Dapr: Scaffold Dapr Tasks.

The Dapr VS Code extension will allow us to manage Dapr application and test it out in an easier way, the below image shows a full list of helper commands.

dapr-vscode-extension

Now we will add 4 tasks, for each application, there will be a task to support the preLaunch activity and the postDebug activity (Terminate/Exit Dapr Sidecar process), so open file tasks.json and add the tasks below:

{
  "tasks": [
    {
      "appId": "tasksmanager-backend-api",
      "appPort": [web api application port number found under properties->launchSettings.json. e.g. 7112],
      "httpPort": 3500,
      "grpcPort": 50001,
      "appSsl": true,
      "label": "backend-api-dapr-debug",
      "type": "dapr",
      "dependsOn": "build-backend-api",
      // Uncomment this line after adding Azure Cosmos DB in module 4
      //"componentsPath": "./components"
    },
    {
      "appId": "tasksmanager-backend-api",
      "label": "daprd-down-backend-api",
      "type": "daprd-down"
    },
    {
      "appId": "tasksmanager-frontend-webapp",
      "appPort": [frontend application port number found under properties->launchSettings.json. e.g. 7112],
      "httpPort": 3501,
      "grpcPort": 50002,
      "appSsl": true,
      "label": "webapp-ui-dapr-debug",
      "type": "dapr",
      "dependsOn": "build-webapp-ui"
    },
    {
      "appId": "tasksmanager-frontend-webapp",
      "label": "webapp-ui-daprd-down",
      "type": "daprd-down"
    }
  ]}
Curious to learn more about the tasks.json file above?
  • The tasks with the label backend-api-dapr-debug will invoke the daprd task. This task is similar to calling dapr run from CLI.
  • We are setting the appPort, httpPort, and grpcPort properties (grpcPort is needed in future modules when we start using the state manager building block. If you didn't set it, you might face a similar issue)
  • We are setting the “componentsPath” property. This is needed when start working with the state manager, pub/sub, etc.
  • We are setting the dependsOn property, so this means this task will fire after the dependsOn tasks complete successfully. We need to add those dependsOn tasks.
  • The tasks with the label daprd-down-backend-api will terminate the Dapr Sidecar process. This will be used for the postDebug activity in configuration.json.
  • For a complete list of available properties please check this link.

Next let's add the dependsOn tasks. Open tasks.json and add the tasks below:

tasks.json
{
    "label": "build-backend-api",
    "command": "dotnet",
    "type": "process",
    "args": [
        "build",
        "${workspaceFolder}/TasksTracker.TasksManager.Backend.Api/TasksTracker.TasksManager.Backend.Api.csproj",
        "/property:GenerateFullPaths=true",
        "/consoleloggerparameters:NoSummary"
    ],
    "problemMatcher": "$msCompile"
},
{
    "label": "build-webapp-ui",
    "command": "dotnet",
    "type": "process",
    "args": [
        "build",
        "${workspaceFolder}/TasksTracker.WebPortal.Frontend.Ui/TasksTracker.WebPortal.Frontend.Ui.csproj",
        "/property:GenerateFullPaths=true",
        "/consoleloggerparameters:NoSummary"
    ],
    "problemMatcher": "$msCompile"
}
Looking for complete tasks.json?
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build-backend-api",
            "command": "dotnet",
            "type": "process",
            "args": [
                "build",
                "${workspaceFolder}/TasksTracker.TasksManager.Backend.Api/TasksTracker.TasksManager.Backend.Api.csproj",
                "/property:GenerateFullPaths=true",
                "/consoleloggerparameters:NoSummary"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "publish-backend-api",
            "command": "dotnet",
            "type": "process",
            "args": [
                "publish",
                "${workspaceFolder}/TasksTracker.TasksManager.Backend.Api/TasksTracker.TasksManager.Backend.Api.csproj",
                "/property:GenerateFullPaths=true",
                "/consoleloggerparameters:NoSummary"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "watch-backend-api",
            "command": "dotnet",
            "type": "process",
            "args": [
                "watch",
                "run",
                "--project",
                "${workspaceFolder}/TasksTracker.TasksManager.Backend.Api/TasksTracker.TasksManager.Backend.Api.csproj"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "build-webapp-ui",
            "command": "dotnet",
            "type": "process",
            "args": [
                "build",
                "${workspaceFolder}/TasksTracker.WebPortal.Frontend.Ui/TasksTracker.WebPortal.Frontend.Ui.csproj",
                "/property:GenerateFullPaths=true",
                "/consoleloggerparameters:NoSummary"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "publish-webapp-ui",
            "command": "dotnet",
            "type": "process",
            "args": [
                "publish",
                "${workspaceFolder}/TasksTracker.WebPortal.Frontend.Ui/TasksTracker.WebPortal.Frontend.Ui.csproj",
                "/property:GenerateFullPaths=true",
                "/consoleloggerparameters:NoSummary"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "watch-webapp-ui",
            "command": "dotnet",
            "type": "process",
            "args": [
                "watch",
                "run",
                "--project",
                "${workspaceFolder}/TasksTracker.WebPortal.Frontend.Ui/TasksTracker.WebPortal.Frontend.Ui.csproj"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "build-processor-svc",
            "command": "dotnet",
            "type": "process",
            "args": [
                "build",
                "${workspaceFolder}/TasksTracker.Processor.Backend.Svc/TasksTracker.Processor.Backend.Svc.csproj",
                "/property:GenerateFullPaths=true",
                "/consoleloggerparameters:NoSummary"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "publish-processor-svc",
            "command": "dotnet",
            "type": "process",
            "args": [
                "publish",
                "${workspaceFolder}/TasksTracker.Processor.Backend.Svc/TasksTracker.Processor.Backend.Svc.csproj",
                "/property:GenerateFullPaths=true",
                "/consoleloggerparameters:NoSummary"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "watch-processor-svc",
            "command": "dotnet",
            "type": "process",
            "args": [
                "watch",
                "run",
                "--project",
                "${workspaceFolder}/TasksTracker.Processor.Backend.Svc/TasksTracker.Processor.Backend.Svc.csproj"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "build-all",
            "dependsOn": [
                "build-backend-api",
                "build-webapp-ui",
                "build-processor-svc"
            ],
            "problemMatcher": [],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        },
        {
            "appId": "tasksmanager-backend-api",
            "appPort": 7088,
            "httpPort": 3500,
            "grpcPort": 50001,
            "appSsl": true,
            "label": "backend-api-dapr-debug",
            "type": "dapr",
            "dependsOn": "build-backend-api",
            "componentsPath": "./components"
        },
        {
            "appId": "tasksmanager-backend-api",
            "label": "daprd-down-backend-api",
            "type": "daprd-down"
        },
        {
            "appId": "tasksmanager-frontend-webapp",
            "appPort": 7208,
            "httpPort": 3501,
            "grpcPort": 50002,
            "appSsl": true,
            "label": "webapp-ui-dapr-debug",
            "type": "dapr",
            "dependsOn": "build-webapp-ui"
        },
        {
            "appId": "tasksmanager-frontend-webapp",
            "label": "webapp-ui-daprd-down",
            "type": "daprd-down"
        },
        {
            "appId": "tasksmanager-backend-processor",
            "appPort": 7263,
            "httpPort": 3502,
            "grpcPort": 50003,
            "appSsl": true,
            "label": "processor-svc-dapr-debug",
            "type": "dapr",
            "dependsOn": "build-processor-svc",
            "componentsPath": "./components"
        },
        {
            "appId": "tasksmanager-backend-processor",
            "label": "processor-svc-daprd-down",
            "type": "daprd-down"
        }
    ]
}

Lastly, we need to add a compound launch property, so we launch and debug both applications together.

To accomplish this, open the file launch.json again and add the below array after the configuration array.

launch.json
"compounds": [
    {
        "name": "RunAll with Dapr",
        "configurations": [
            "Launch (backend api) with Dapr",
            "Launch (web app) with Dapr"
        ],
        "stopAll": true
    }
]

Success

If all is done correctly, you should be able to see a debug configuration named RunAll with Dapr and you should be able to just hit ++F5++, sit breakpoints and debug both applications locally in VS Code.

dapr-vscode-debug


Last update: 2023-06-02