# GitHub Actions example
- run: dotnet restore
- run: dotnet build --no-restore -c Release
- run: dotnet test --no-build -c Release
- run: dotnet publish -c Release -o ./publish
- run: docker build -t myapp:${{ github.sha }} .
Topics
31
.NET CLI, SDK & Project Structure (csproj)
.NET vs .NET Framework
API Versioning
ASP.NET Core Middleware & Request Pipeline
Assemblies & NuGet
Authentication & Authorization (Identity, JWT, OAuth)
Background Services
Blazor (Server & WebAssembly)
Caching (In-Memory, Distributed & Redis)
CI/CD, Publishing & Deployment
CLR & Runtime
Configuration & Options
CORS & Cross-Origin Resource Sharing
Dependency Injection
Diagnostics & Performance
Docker & Containerization
Entity Framework Core & Data Access
Generic Host
Global Exception Handling & Middleware
gRPC Services
Health Checks & Readiness/Liveness Probes
Logging
Microservices & Distributed Architecture Patterns
Minimal APIs
MVC & Razor Pages
Rate Limiting & Throttling
RESTful Web APIs & Controllers
Secrets Management & Configuration Providers (Key Vault, User Secrets)
SignalR & Real-Time Communication
Testing in .NET (xUnit, Integration & Unit Testing)
Worker Services & IHostedService
CI/CD, Publishing & Deployment
16 questions found
A typical pipeline includes: restore dependencies (dotnet restore), build (dotnet build), run automated tests (dotnet test), publish deployable artifacts (dotnet publish), and deploy to a target environment (container registry, cloud platform, or server) -- often gated by required checks like code coverage thresholds, security scans, and manual approval for production deployments.
Real-world example
A team's pipeline automatically blocks merging any pull request where dotnet test fails or code coverage drops below 80%, catching regressions before they ever reach the main branch.
.NET CLI
SDK & Project Structure (csproj);Docker & Containerization
How do you configure a GitHub Actions workflow to build, test, and publish a .NET application?
IntermediateA GitHub Actions workflow YAML file defines jobs with steps using the actions/setup-dotnet action to install the required SDK version, followed by standard dotnet CLI commands, with results and artifacts optionally uploaded using actions/upload-artifact for use in subsequent deployment jobs.
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with: { dotnet-version: '8.0.x' }
- run: dotnet restore
- run: dotnet build --no-restore -c Release
- run: dotnet test --no-build -c Release --logger trx
- uses: actions/upload-artifact@v4
with: { name: test-results, path: '**/*.trx' }
Real-world example
A team's GitHub Actions workflow runs on every pull request, automatically posting test results and coverage reports as a PR comment before a reviewer even opens the code, catching issues early in the review process.
.NET CLI
SDK & Project Structure (csproj);Testing in .NET (xUnit
Integration & Unit Testing)
What is the difference between blue-green deployment and canary deployment, and how do they apply to .NET applications?
AdvancedBlue-green deployment maintains two identical production environments (blue = current, green = new), routing all traffic to green only after it's fully deployed and verified, enabling instant rollback by switching traffic back to blue if issues arise. Canary deployment instead gradually shifts a small percentage of traffic to the new version, monitoring for errors before progressively increasing that percentage -- reducing blast radius of a bad deployment compared to blue-green's all-at-once cutover, at the cost of more complex traffic-splitting infrastructure.
# Canary deployment via Kubernetes traffic splitting
apiVersion: split.smi-spec.io/v1alpha3
kind: TrafficSplit
spec:
service: myapp
backends:
- service: myapp-v1
weight: 90
- service: myapp-v2
weight: 10 # only 10% of traffic hits the new version initially
Real-world example
A payments API uses canary deployment, routing 5% of traffic to a new version for an hour while monitoring error rates and latency, only proceeding to 100% rollout if no anomalies are detected, versus a less risk-averse internal tool that uses simpler blue-green cutover.
Microservices & Distributed Architecture Patterns;Diagnostics & Performance
How do you securely manage secrets (connection strings, API keys) in a CI/CD pipeline without committing them to source control?
IntermediateCI/CD platforms provide encrypted secret storage (GitHub Actions Secrets, Azure DevOps variable groups with secret variables, GitLab CI/CD variables) injected as environment variables only during pipeline execution, never exposed in logs or the repository itself -- combined with cloud-native secret managers (Azure Key Vault, AWS Secrets Manager) for runtime application secrets, keeping build-time and run-time secret concerns properly separated.
# GitHub Actions: referencing a repository secret
- name: Deploy
env:
CONNECTION_STRING: ${{ secrets.PROD_DB_CONNECTION_STRING }}
run: dotnet run --project deploy-tool
Real-world example
A pipeline deploying to Azure retrieves its deployment credentials from GitHub Actions Secrets rather than a hardcoded config file, and the application itself retrieves its database connection string from Azure Key Vault at runtime rather than from pipeline-injected environment variables.
Secrets Management & Configuration Providers (Key Vault
User Secrets);Configuration & Options
How do you set up automated database migrations as part of a .NET CI/CD deployment pipeline safely?
AdvancedCommon safe approaches include: running EF Core migrations (`dotnet ef database update`) as a separate pipeline step before deploying application code (so the schema is ready before new code that depends on it runs), using the expand-contract pattern for backward-compatible schema changes so old and new application versions can both run against the migrated schema briefly during rollout, and always taking a database backup or snapshot immediately before applying migrations in production as a safety net.
# Pipeline step: apply migrations before deploying app
- name: Apply migrations
run: dotnet ef database update --project src/MyApp.Data --connection "$PROD_CONNECTION_STRING"
- name: Deploy application
run: az webapp deploy --resource-group myapp-rg --name myapp --src-path ./publish.zip
Real-world example
A team's deployment pipeline runs EF Core migrations as a distinct, monitored step with automatic rollback triggers, deliberately separated from the application deployment step so a failed migration halts the pipeline before any new application code goes live against a broken schema.
Entity Framework Core & Data Access;Diagnostics & Performance
What is the purpose of separate build and release pipelines (or stages), and why shouldn't you rebuild the application for each deployment environment?
IntermediateSeparating build (compile once, producing a single versioned, immutable artifact) from release (deploy that same exact artifact to dev, then staging, then production) ensures you're testing and deploying the literal same binary throughout the pipeline, eliminating the risk of environment-specific build differences causing 'it worked in staging but not production' bugs -- environment-specific configuration should be injected at deploy time (via config files or environment variables), not baked in via a fresh rebuild per environment.
# Build once
dotnet publish -c Release -o ./artifacts
# Deploy the SAME artifact to each environment, varying only config
# Deploy to staging: uses staging appsettings/env vars
# Deploy to production: uses production appsettings/env vars (same binary)
Real-world example
A team eliminates a class of 'works in staging, breaks in production' bugs by switching from rebuilding the app separately for each environment to building one artifact once and promoting that exact same build through staging and then production.
Configuration & Options;.NET CLI
SDK & Project Structure (csproj)
How does deployment slot swapping (e.g., Azure App Service deployment slots) enable near-zero-downtime deployments?
AdvancedDeployment slots let you deploy a new version to a separate, fully warmed-up staging slot (with its own URL for testing) and then perform an atomic swap that exchanges the staging and production slot's routing, making the new version live instantly with the previously-production version now sitting in staging (as an instant rollback target) -- avoiding the cold-start delay and brief unavailability of a traditional stop-deploy-start deployment.
az webapp deployment slot create --name myapp --resource-group myapp-rg --slot staging
az webapp deployment source config-zip --resource-group myapp-rg --name myapp --slot staging --src ./publish.zip
# After verifying staging slot works correctly:
az webapp deployment slot swap --resource-group myapp-rg --name myapp --slot staging --target-slot production
Real-world example
An e-commerce site deploys a new version to a staging slot, runs automated smoke tests against its dedicated URL, and only then swaps it into production, keeping the previous version instantly available in the staging slot for immediate rollback if any issue is discovered post-swap.
Docker & Containerization;Health Checks & Readiness/Liveness Probes
What is the role of automated smoke tests and health checks immediately after a deployment completes?
IntermediatePost-deployment smoke tests (a small suite of critical-path checks, like 'can the app respond to a basic request' or 'can it reach the database') and health check endpoint verification confirm the newly deployed version is actually functioning correctly before fully committing to it or routing significant traffic to it, catching deployment-specific issues (missing config, failed migration, broken dependency) immediately rather than discovering them from user-facing errors or alerts minutes or hours later.
# Pipeline step after deployment
- name: Smoke test
run: |
response=$(curl -s -o /dev/null -w "%{http_code}" https://myapp.com/health)
if [ "$response" != "200" ]; then
echo "Health check failed, initiating rollback"
exit 1
fi
Real-world example
A pipeline automatically triggers a rollback to the previous deployment slot if the post-deployment smoke test against the /health endpoint doesn't return 200 within 60 seconds of the swap, catching a bad deployment before real users are affected.
Health Checks & Readiness/Liveness Probes;Diagnostics & Performance
How does GitOps (e.g., using Flux or ArgoCD with Kubernetes) change the deployment model compared to traditional push-based CI/CD pipelines?
AdvancedIn GitOps, a Git repository is the single source of truth for the desired deployment state (Kubernetes manifests, Helm charts), and a controller running inside the cluster continuously reconciles the actual cluster state to match what's declared in Git (pull-based), rather than a CI pipeline directly pushing changes to the cluster (push-based) -- this provides a full audit trail via Git history, easy rollback (revert the Git commit), and eliminates the need to grant CI systems direct write credentials to production infrastructure.
# GitOps flow:
# 1. Developer merges PR updating image tag in deployment.yaml
# 2. Flux/ArgoCD controller (running IN the cluster) detects the Git change
# 3. Controller pulls the new manifest and reconciles cluster state to match
# CI pipeline never has direct cluster write access
Real-world example
A platform team adopts ArgoCD so that rolling back a bad .NET microservice deployment is as simple as reverting a Git commit, with the in-cluster controller automatically detecting and applying the reverted state within seconds, without needing direct pipeline access to production credentials.
Docker & Containerization;Microservices & Distributed Architecture Patterns
How do you version and tag Docker images for a .NET application as part of a CI/CD pipeline?
IntermediateA common convention tags images with both a unique, traceable identifier (like the Git commit SHA, ensuring every build is uniquely identifiable and immutable) and a semantic or environment-meaningful tag (like 'latest' for the most recent build, or a version number for releases), pushing both tags to the container registry so deployments can reference either the exact commit or a more human-friendly version.
docker build -t myregistry.io/myapp:${{ github.sha }} -t myregistry.io/myapp:v1.4.0 .
docker push myregistry.io/myapp:${{ github.sha }}
docker push myregistry.io/myapp:v1.4.0
Real-world example
A team always deploys using the specific Git SHA tag (never 'latest') in their Kubernetes manifests, guaranteeing that a rollback or audit can always trace exactly which commit is running in production at any point in time.
Docker & Containerization;.NET CLI
SDK & Project Structure (csproj)
Showing 1–10 of 16