This guide will help you set up your local development environment for working on the Essential C# Web project.
- Visual Studio (or your preferred IDE)
- .NET 10.0 SDK — verify with
dotnet --info
For basic browsing and UI development, no secrets are needed. The database connection and HCaptcha test keys are already configured in appsettings.Development.json.
-
Clone the repository.
-
Configure the package feed in Directory.Packages.props:
- Leave
<AccessToNugetFeed>false</AccessToNugetFeed>(the default) when you do not have Azure DevOps feed access. Public packages restore from nuget.org, internal content packages are excluded, and the app uses placeholder content. - Set
<AccessToNugetFeed>true</AccessToNugetFeed>only when you have authenticated access to the private Azure DevOps feed and need the internal content packages. - When troubleshooting package restore or SDK version issues, set it to
falsefirst to isolate public NuGet dependencies and avoid private-feed authentication errors.
- Leave
-
Restore and build the solution:
dotnet restore dotnet build --configuration Debug --no-restore
-
Install and build the frontend assets:
npm ci --prefix EssentialCSharp.Web npm run build --prefix EssentialCSharp.Web
-
Start the web application:
dotnet run --project EssentialCSharp.Web
Open the HTTPS URL printed by the application (typically
https://localhost:7184).
Database note: The Development connection string targets SQL Server on
localhost. Start a local SQL Server instance, or overrideConnectionStrings__EssentialCSharpWebContextConnectionbefore running the application.
When ASPNETCORE_ENVIRONMENT is Development (local runs), the web application applies EF Core migrations on startup. Deployed environments (the Azure Dev app runs as Staging) do not; they use the migration bundle below. For local development, make sure the database connection is configured and SQL Server is available before running the app. You can also apply migrations manually with the repository's local tools:
dotnet tool restore
dotnet tool run dotnet-ef -- database update --project EssentialCSharp.WebFor both Azure deployments (Dev and Prod), the pipeline builds a Linux EF migration bundle into the web image and runs it as a manual Azure Container Apps Job before updating the web app. The job uses the environment's Key Vault-backed SQL connection configuration. A failed migration prevents the app update, but the database is not automatically rolled back. Because the migration runs while the current app may still be serving requests, breaking or long-running schema changes can cause errors or downtime; review generated migrations before deployment.
The Development and Production GitHub Environments each need a MIGRATION_JOB_NAME variable set to the corresponding Terraform output (dev_web_migration_job_name or prod_web_migration_job_name from the Azure Resource Management root module).
Tip: Use the dotnet secret manager for any secrets below:
dotnet user-secrets set "<Key>" "<Value>" --project EssentialCSharp.Web
These features are disabled or use safe defaults in Development unless explicitly configured.
Required to enable the chat widget. Skipped entirely in Development if not configured.
AIOptions:Endpoint = https://<your-azure-openai-resource>.openai.azure.com/
AIOptions:VectorGenerationDeploymentName = text-embedding-3-large-v1
AIOptions:ChatDeploymentName = gpt-4o
ConnectionStrings:PostgresVectorStore = <postgres-connection-string>
The MCP endpoint (/mcp) is always running. To generate tokens via the Account > MCP Access page, no additional config is needed — tokens are stored in the local database.
TryDotNet:Origin = https://<trydotnet-origin>
Use one of these — not both simultaneously (they conflict).
# Azure Monitor (Application Insights):
APPLICATIONINSIGHTS_CONNECTION_STRING = InstrumentationKey=...
# Local Aspire dashboard (OTLP):
OTEL_EXPORTER_OTLP_ENDPOINT = http://localhost:4317
These are only required outside of Development. The app throws at startup if they are missing in non-Development environments.
AuthMessageSender:SendFromName = Hello World Team
AuthMessageSender:SendFromEmail = no-reply@email.com
AuthMessageSender:SecretKey = <mailjet-secret-key>
AuthMessageSender:APIKey = <mailjet-api-key>
Authentication:Microsoft:ClientId = <client-id>
Authentication:Microsoft:ClientSecret = <client-secret>
Authentication:github:clientId = <client-id>
Authentication:github:clientSecret = <client-secret>
Development uses hCaptcha test keys by default. Override for production:
HCaptcha:SiteKey = <site-key>
HCaptcha:SecretKey = <secret-key>