Local debugging guide — C#
This guide covers everything specific to debugging an Extend Service Extension app written in C#. For concepts that apply to all languages — architecture, environment variables, log format, and common issues — see the main debugging guide.
Prerequisites
-
.NET SDK 8.0 or later — verify with:
dotnet --version
# Expected: 8.x.x or later -
VS Code C# extension (
ms-dotnettools.csharp, C# Dev Kit) — install from the VS Code marketplace or accept the recommended extensions prompt when you open the repository. -
AccelByte credentials —
AB_BASE_URL,AB_CLIENT_ID,AB_CLIENT_SECRET, andBASE_PATH. See Environment setup in the main guide.
Project structure
src/
└── AccelByte.Extend.ServiceExtension.Server/
├── AccelByte.Extend.ServiceExtension.Server.csproj
├── Program.cs # Entry point
├── Classes/
│ ├── AuthorizationInterceptor.cs # IAM token and permission validation
│ └── ...
├── Protos/
│ ├── service.proto # gRPC API definition
│ └── ...
└── Services/
└── MyService.cs # Your business logic
| File | What it does |
|---|---|
Program.cs | Entry point — wires gRPC server, gRPC-Gateway, metrics, and auth. |
Services/MyService.cs | Your business logic — implements the gRPC service methods. |
Classes/AuthorizationInterceptor.cs | Validates every incoming request's IAM token and permission. |
Protos/service.proto | Defines the gRPC API — endpoints, request/response shapes, and required permissions. |
Port numbers:
| Port | Purpose |
|---|---|
6565 | gRPC server (internal — used by gRPC-Gateway) |
8000 | gRPC-Gateway HTTP/REST — call this from a browser, Postman, or curl |
8080 | Prometheus metrics endpoint (/metrics) |
Running the service locally
From the terminal
# Export all variables from your .env file
export $(grep -v '^#' .env | xargs)
dotnet run --project src/AccelByte.Extend.ServiceExtension.Server
From VS Code
Use Terminal → Run Task → "Run: Service".
This task is defined in .vscode/tasks.json and loads the .env file for you automatically.
Confirming the service is up
You should see logs like:
{"time":"...","level":"INFO","msg":"app server started","service":"extend-app-service-extension"}
{"time":"...","level":"INFO","msg":"starting gRPC-Gateway HTTP server","port":8000}
{"time":"...","level":"INFO","msg":"serving prometheus metrics","port":8080,"endpoint":"/metrics"}
Open http://localhost:8000<BASE_PATH>/apidocs/ in your browser to verify Swagger UI is live.
Attaching the debugger
VS Code (recommended)
The repository ships with a ready-to-use launch configuration in .vscode/launch.json that
uses the built-in .NET debugger (coreclr):
{
"name": "Debug: Service",
"type": "coreclr",
"request": "launch",
"program": "${workspaceFolder}/src/AccelByte.Extend.ServiceExtension.Server/bin/Debug/net8.0/AccelByte.Extend.ServiceExtension.Server.dll",
"envFile": "${workspaceFolder}/.env",
"cwd": "${workspaceFolder}",
"console": "integratedTerminal"
}
Steps:
- Fill in
.env(see Environment setup). - Open the Run and Debug panel (
Ctrl+Shift+D/Cmd+Shift+D). - Select "Debug: Service" from the dropdown.
- Press F5.
VS Code builds the project with debug symbols and starts it under the .NET debugger.
Other IDEs
Start the app with diagnostics enabled, then attach your IDE using "Attach to process":
export $(grep -v '^#' .env | xargs)
DOTNET_EnableDiagnostics=1 dotnet run --project src/AccelByte.Extend.ServiceExtension.Server
Most IDEs (JetBrains Rider, Visual Studio) support attaching to a running .NET process via Run → Attach to process.
Where to put breakpoints
| What you want to investigate | File and location |
|---|---|
| A specific REST endpoint being called | Services/MyService.cs — top of the relevant method |
| Auth/token validation failure | Classes/AuthorizationInterceptor.cs — the Intercept method |
| Data not saving or loading correctly | The storage/repository class used in your service |
| Service not starting at all | Program.cs — the startup initialization block |
Conditional breakpoint syntax
Right-click a breakpoint → Edit Breakpoint → enter a C# expression, for example:
request.GuildId == "guild_001"
The debugger only pauses when the condition is true.
Reading logs
Pipe output through jq for readable JSON logs:
dotnet run --project src/AccelByte.Extend.ServiceExtension.Server 2>&1 | jq '.'
# Show only ERROR lines
dotnet run --project src/AccelByte.Extend.ServiceExtension.Server 2>&1 | jq 'select(.level == "ERROR")'
Testing endpoints manually
curl
# Create or update guild progress
curl -s -X POST \
"http://localhost:8000/guild/v1/admin/namespace/mygame/progress" \
-H "Content-Type: application/json" \
-d '{"guildProgress": {"guildId": "guild_001", "namespace": "mygame"}}' | jq .
# Get guild progress
curl -s "http://localhost:8000/guild/v1/admin/namespace/mygame/progress/guild_001" | jq .
Add -H "Authorization: Bearer <your-token>" when PLUGIN_GRPC_SERVER_AUTH_ENABLED=true.
grpcurl (gRPC layer directly)
# List available services
grpcurl -plaintext localhost:6565 list
# Call a method directly
grpcurl -plaintext \
-d '{"namespace":"mygame","guildProgress":{"guildId":"guild_001"}}' \
localhost:6565 service.Service/CreateOrUpdateGuildProgress
C#-specific troubleshooting
Proto changes have no effect
Symptom: You edited Protos/service.proto but nothing changed at runtime.
Cause: The generated gRPC stubs have not been rebuilt.
Fix: Run a clean build:
dotnet build src/AccelByte.Extend.ServiceExtension.Server
The .csproj file includes a <Protobuf> item that triggers code generation automatically
on build. If you still see stale behavior, run:
dotnet clean && dotnet build src/AccelByte.Extend.ServiceExtension.Server
DOTNET_ENVIRONMENT and configuration sources
The app may read additional configuration from appsettings.json or environment-specific
variants (appsettings.Development.json). Set DOTNET_ENVIRONMENT=Development in your .env
to activate development-mode configuration.
Checking for port conflicts
If you see "address already in use":
ss -tlnp | grep -E '6565|8000|8080'
Kill the stale process and start again.
AI assistance
The app template ships with a Claude agent skill at
.claude/skills/debugging-guide/SKILL.md.
Copy the full skill file into your own repository and activate it in your AI assistant.
For the full skill content and prompting tips, see the AI assistance section in the main guide.