
Add Dotnet Service
- 1 installs
- Updated May 18, 2026
- duncan-g/bootstrapproject
Add a new .NET gRPC service to an Aspire-orchestrated project: scaffold under services, bind on 0.0.0.0, register in the AppHost, and update Envoy if present.
About
Adds a .NET gRPC service to an Aspire project, scaffolding it, wiring AppHost registration, and updating the Envoy proxy when it exists. A developer uses it during or after bootstrap to add a backend service.
- Scaffolds gRPC service with dynamic Aspire port binding
- Registers in AppHost and updates Envoy routes post-bootstrap
Add Dotnet Service by the numbers
- 1 all-time installs (skills.sh)
- Ranked #121 of 153 .NET & C# skills by installs in the Skillselion catalog
- Data as of Jul 8, 2026 (Skillselion catalog sync)
npx skills add https://github.com/duncan-g/bootstrapproject --skill add-dotnet-serviceAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| Last updated | May 18, 2026 |
| Repository | duncan-g/bootstrapproject ↗ |
What it does
Add a new .NET gRPC service to an Aspire-orchestrated project: scaffold under services, bind on 0.0.0.0, register in the AppHost, and update Envoy if present.
Files
Add .NET gRPC Service
Adds a single .NET gRPC service to an Aspire-orchestrated project. Works in two contexts:
- During bootstrap — called by
bootstrap-project. Envoy does not
exist yet; the orchestrator creates it later with the full route set.
- Standalone — called directly on an already-bootstrapped project.
Envoy exists and this skill updates it.
Placeholders
«ProjectName»— PascalCase root namespace, detected from the AppHost
.csproj filename (e.g. Nimbus.AppHost.csproj → Nimbus).
«ServiceName»— PascalCase name for this service (e.g.Billing).«servicename»— lowercase folder and Aspire resource name (e.g.
billing).
«SERVICENAME»— UPPERCASE form for Envoy env var prefixes (e.g.
BILLING).
Prerequisites
apphost/exists with a working.csprojandProgram.cs.services/directory exists.dotnetCLI is available.
Step 1 — Gather inputs
Ask the user for:
1. Service name — short, lowercase (e.g. billing, notifications). Derive PascalCase and UPPERCASE forms automatically. 2. Envoy route prefix — defaults to /«servicename»/.
Detect «ProjectName» from the AppHost .csproj:
ls apphost/*.csprojThe name before .AppHost.csproj is the project name.
Step 2 — Scaffold the service
dotnet new grpc -n «ProjectName».«ServiceName» -o services/«servicename»
dotnet build services/«servicename»Per bootstrap-project principle 2: if a flag is rejected, drop it and re-run.
Step 3 — Set RootNamespace
Ensure the .csproj has an explicit <RootNamespace> of «ProjectName».«ServiceName» inside the first <PropertyGroup>:
<RootNamespace>«ProjectName».«ServiceName»</RootNamespace>This guarantees the generated namespace is «ProjectName».«ServiceName» regardless of folder structure or project name conventions. If the element already exists with the correct value, leave it as-is.
Step 4 — Bind on 0.0.0.0
Update services/«servicename»/Properties/launchSettings.json: set the http profile's applicationUrl to http://0.0.0.0:0. Port 0 lets Aspire assign dynamically. Do not hardcode a port.
Step 5 — Add ProjectReference to AppHost
Add to apphost/«ProjectName».AppHost.csproj inside the <ItemGroup> containing other <ProjectReference> entries:
<ProjectReference Include="../services/«servicename»/«ProjectName».«ServiceName».csproj" />Step 6 — Register in apphost/Program.cs
Add alongside existing service registrations:
var «servicename» = builder.AddProject<Projects.«ProjectName»_«ServiceName»>("«servicename»");Dots in the project name become underscores in the source-generated type.
Build to verify:
dotnet build apphostStep 7 — Update Envoy (post-bootstrap only)
Check whether proxy/envoy.yaml.tmpl exists.
- File absent — skip this step. The caller (
bootstrap-project)
creates Envoy later with the full route set.
- File present — load `references/update-envoy.md` and follow
it to add the service's route, cluster, entrypoint validation, and AppHost Envoy wiring.
Guardrails
- Never hardcode ports — Aspire assigns them dynamically.
- Service folder is lowercase (
services/billing/);.csprojand
assembly use PascalCase with the root namespace («ProjectName».Billing).
- Resource names in
Program.csare short lowercase strings matching
the folder name.
Update Envoy for a new gRPC service
When proxy/envoy.yaml.tmpl exists, follow these steps to wire a new .NET gRPC service into the Envoy proxy.
Placeholders: «servicename» (lowercase), «SERVICENAME» (UPPERCASE).
---
1. Add route to proxy/envoy.yaml.tmpl
Insert a new route in the routes: list before the catch-all - match: { prefix: "/" } entry:
- match: { prefix: "/«servicename»/" }
route:
cluster: «servicename»
prefix_rewrite: "/"
timeout: 0s
max_stream_duration:
grpc_timeout_header_max: 0sprefix_rewrite: "/"strips the/{service}/prefix so the backend
sees native gRPC paths (/<package>.<Service>/<Method>).
grpc_timeout_header_max: 0sdisables Envoy's default gRPC timeout.
2. Add cluster to proxy/envoy.yaml.tmpl
Append to the clusters: list. gRPC services require http2_protocol_options for h2c upstream:
- name: «servicename»
type: STRICT_DNS
lb_policy: ROUND_ROBIN
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options: {}
load_assignment:
cluster_name: «servicename»
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: __«SERVICENAME»_HOST__
port_value: __«SERVICENAME»_PORT__3. Update proxy/entrypoint.sh
Add require_env calls alongside the existing ones:
require_env «SERVICENAME»_HOST
require_env «SERVICENAME»_PORTAdd sed substitution lines in the final sed command block:
-e "s|__«SERVICENAME»_HOST__|${«SERVICENAME»_HOST}|g" \
-e "s|__«SERVICENAME»_PORT__|${«SERVICENAME»_PORT}|g" \4. Update Envoy wiring in apphost/Program.cs
Add .WaitFor() to the existing envoy builder chain:
envoy.WaitFor(«servicename»);Add .WithClusterEndpoint() alongside existing cluster endpoint calls:
envoy.WithClusterEndpoint(builder, "«SERVICENAME»", «servicename».GetEndpoint("http"));5. Rebuild and verify
dotnet build apphostIf the project was already running, restart with aspire stop then aspire start (or aspire run).