ToolUp Days #15

ToolUp Days #15

2022-10-21

ToolUp Days is all about showing the thought process and decisions made when creating an application from scratch. Episode 15 continues the Codespaces-based development workflow from the previous session, validating the Dapr + Codespaces secrets pattern end-to-end and extending local debugging to a second microservice — before landing in a genuinely puzzling .NET minimal API routing problem.

Quick Context

The episode opens with conference highlights from South Coast Summit and some quick hiring news before getting into the technical work.

First Win: Player State Just Works

The biggest early moment is how little work is needed. With GitHub Codespaces secrets already configured as environment variables and the Dapr environment-variable secret store component already in place from episode 14, a single dapr run --components-path ./components -- dotnet run brings the Player State service fully online. Dapr logs confirm both the secret store and state store components load successfully.

This validates the full setup from the previous session: declarative dev containers + Codespaces secrets + Dapr local components = a development environment that picks up exactly where it left off.

Extending to the World Events Engine

With Player State proven, the team turns to the World Events Engine — a second microservice that listens on an Azure Storage Queue and writes state to Azure Table Storage via Dapr bindings.

Three Dapr component files are needed for this service:

  • secret-store.yaml — the environment-variable secret store (reused from Player State)
  • binding-world-events.yaml — an Azure Storage Queue binding named world-events, using the shared storage account key from the secret store
  • state-world-events.yaml — a Table Storage state store scoped to the world events table

The team reuses the same Codespaces secret for the storage account key across both services, while calling out that a production setup would use separate accounts to avoid hitting live Azure resources during development.

With all three components in place, dapr run for the World Events Engine confirms all components load. A test message is dropped into the Azure Storage Queue from the Azure portal — and after a brief investigation into why Dapr wasn’t receiving it (the app port needs to be specified explicitly with -p 5000), the binding fires and the message is processed.

Debugging Multiple Dapr Services in VS Code

Getting the two services communicating requires running them simultaneously and being able to set breakpoints. This pulls the team into VS Code launch.json and tasks.json configuration for Dapr-based debugging.

The existing launch configs were stale and mixed Docker-debug entries with Dapr ones. The team cleans them up and explores the Dapr VS Code extension, which can scaffold launch configurations for multiple Dapr apps. Running both services at the same time in split terminals is discussed as a pragmatic fallback while the launch config is sorted.

The .NET Minimal API Mystery

The episode’s cliffhanger arrives when the World Events Engine’s Dapr queue binding attempts to call the service’s POST endpoint — and nothing arrives. GET endpoints work correctly, but the POST route that should receive the bound message refuses to bind its body parameter regardless of whether [FromBody], [FromQuery], application/json content type, or form encoding is used.

The team rules out Dapr interference (since it’s just an SDK at this point), tries controller-based routing, deletes and regenerates the launch files, and ultimately runs out of time with the issue unresolved. The closing thought: “We at least know what we need to be looking at. It’s something in that .NET app.”

The session closes with homework assigned, the next date confirmed (15 November), and an open invitation for anyone recognising the problem to share the solution in the comments.

Related Content

ToolUp Days #14

ToolUp Days #14

2022-10-07

Chris and Matt solve a recurring ToolUp Days pain point — inconsistent developer environments — by setting up GitHub Codespaces with a custom dev container. They extend a community .NET template to include Go, configure Dapr component files for local Azure Storage access, and leverage Codespaces secrets as injected environment variables to avoid storing credentials in source code. By the end of the session they have a fully reproducible, cloud-hosted development environment that spins up in seconds.

ToolUp Days #11

ToolUp Days #11

2022-08-23

The series officially rebrands from ToolUp Tuesday to ToolUp Days, giving Chris and Matt the flexibility to keep a consistent cadence. This episode focuses on rethinking the game's data model — simplifying the player state object, introducing a BarType enum, and scaffolding both a player creation API and a bar management controller, with GitHub Copilot generating much of the boilerplate in real time.

ToolUp Tuesday - #6

ToolUp Tuesday - #6

2022-05-03

Chris and Matt wire up Dapr state management for their .NET player state service, configure VS Code debugging for multi-service development, and document game use cases covering player enrollment, world event ticks, and decision lifecycle.