Appearance
Are you an LLM? You can read better optimized documentation at /reference/environments.md for this page in Markdown format
Environment reference
This document provides a detailed technical reference for the various runtime environments supported by TheExampleApp. Understanding these configurations is crucial for development, testing, and deployment. The application leverages ASP.NET Core's environment feature, which is primarily controlled by the ASPNETCORE_ENVIRONMENT environment variable.
For a general overview of how application settings and environment variables are managed, please refer to the Application Settings and Environment Variables documentation.
Environment configuration
The application's behavior changes significantly based on the runtime environment. ASP.NET Core uses the IHostingEnvironment service to identify the current environment. The environment is typically set to Development, Staging, or Production. This application also defines a custom Heroku environment.
The environment is determined by the ASPNETCORE_ENVIRONMENT environment variable.
Local Development: In local development, this variable is configured in Properties/launchSettings.json, which sets the environment to Development for both IIS Express and Kestrel launch profiles.
json:TheExampleApp/Properties/launchSettings.json
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:56497/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "http://localhost:59989/",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" // Sets the environment for IIS Express
}
},
"TheExampleApp": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" // Sets the environment for Kestrel
},
"applicationUrl": "http://localhost:3000/"
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Containerized Deployment (Heroku): For container-based deployments, the environment is set within the Dockerfile.
dockerfile:Dockerfile
# ...
FROM microsoft/aspnetcore:2.1
WORKDIR /app
ENV ASPNETCORE_ENVIRONMENT=Heroku // Sets the environment for the container
COPY --from=builder /app .
ENTRYPOINT ["dotnet", "TheExampleApp.dll"]1
2
3
4
5
6
2
3
4
5
6
The Startup.cs file uses extension methods like env.IsDevelopment() and env.IsStaging() to conditionally configure services and middleware.
Development
The Development environment is optimized for the developer feedback loop, prioritizing detailed error information over security and performance.
Developer Exception Page
When an unhandled exception occurs, a detailed error page is displayed, including the stack trace, query parameters, headers, and cookies. This is enabled by app.UseDeveloperExceptionPage().
csharp:TheExampleApp/Startup.cs
// In Configure method
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage(); // Shows detailed exception info in the browser
app.UseBrowserLink();
}
else
{
// ... production error handling
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Warning: This middleware should never be enabled in a production or staging environment as it can expose sensitive application internals.
Browser Link
Browser Link is enabled to provide a real-time connection between Visual Studio and the browser, allowing for automatic page refreshes when source files are changed. This is enabled by app.UseBrowserLink().
Detailed Logging
The appsettings.Development.json file configures a more verbose logging level to aid in debugging. The default log level is set to Debug.
json:TheExampleApp/appsettings.Development.json
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug", // Enables detailed logging for all categories
"System": "Information",
"Microsoft": "Information"
}
}
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Staging
The Staging environment is designed to mirror production as closely as possible while allowing for testing against non-production data sources. It uses a specific configuration file, appsettings.Staging.json, and custom logic to retarget API requests.
Custom Staging Host Support
The application can be configured to fetch content from a staging instance of the Contentful API. This is achieved by setting a StagingHost environment variable. If this variable is present, the application registers a custom HttpClient that intercepts and rewrites requests to Contentful.
csharp:TheExampleApp/Startup.cs
// In ConfigureServices method
if (CurrentEnvironment.IsStaging())
{
var host = Environment.GetEnvironmentVariable("StagingHost");
if (!string.IsNullOrEmpty(host))
{
services.AddSingleton((ip) =>
{
// Register a custom message handler for the HttpClient
var stagingHandler = new StagingMessageHandler
{
StagingHost = host
};
return new HttpClient(stagingHandler);
});
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
StagingMessageHandler
The StagingMessageHandler is a custom HttpClientHandler that uses a regular expression to replace the host in any request URL containing "contentful" with the host specified in the StagingHost environment variable. This allows the application to seamlessly switch its content source without changing the core SDK logic.
csharp:TheExampleApp/Startup.cs
public class StagingMessageHandler : HttpClientHandler
{
public string StagingHost { get; set; }
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Intercept outgoing HTTP requests
var regex = new Regex("contentful");
// Replace the first occurrence of "contentful" in the URL's host with the staging host
var req = regex.Replace(request.RequestUri.ToString(), StagingHost, 1);
request.RequestUri = new Uri(req);
return await base.SendAsync(request, cancellationToken);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
Staging-specific Configuration
The appsettings.Staging.json file provides the necessary Contentful API keys and Space ID for the staging environment, as well as logging configuration.
json:TheExampleApp/appsettings.Staging.json
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
"ContentfulOptions": {
"DeliveryApiKey": "3048cf48001c0a5f2d0cdd2135f4fa7b80f93e36452381a0a32b0f81c8ca8063",
"PreviewApiKey": "d477447bd0ba58db88009e5eae6d033d524730a700010952f30300d7810b861a",
"SpaceId": "9leupbwh43vu",
"UsePreviewApi": false
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
For more details on these settings, see the Configuration Reference.
Production
The Production environment (and any other non-development environment like Staging and Heroku) is configured for robustness, security, and performance.
HTTPS Enforcement
The application enforces HTTPS by inspecting the X-Forwarded-Proto header. This is a critical feature for applications running behind a reverse proxy or load balancer (like Heroku's router) that terminates SSL. If a request is received via HTTP, a 301 Moved Permanently redirect is issued to the corresponding https URL.
This logic is implemented as a custom rewrite rule in Startup.cs.
csharp:TheExampleApp/Startup.cs
// In Configure method, inside the non-development block
options.Add((c) => {
var request = c.HttpContext.Request;
// Check if the request was forwarded and the original protocol was HTTP
if(request.Headers.ContainsKey("X-Forwarded-Proto") && request.Headers["X-Forwarded-Proto"] == "http")
{
var response = c.HttpContext.Response;
response.StatusCode = StatusCodes.Status301MovedPermanently;
c.Result = RuleResult.EndResponse;
// Construct the new HTTPS URL and set the Location header
response.Headers[HeaderNames.Location] = "https://" + request.Host + request.Path + request.QueryString;
}
});
app.UseRewriter(options);1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
Error Handling
Instead of the developer exception page, non-development environments use a generic, user-friendly error handler.
app.UseExceptionHandler("/Error"): This middleware catches unhandled exceptions and re-executes the request pipeline with the path/Error, displaying a safe, user-facing error page.
Additionally, for all environments (including Development):
app.UseStatusCodePagesWithReExecute("/Error"): This handles non-success status codes that are not exceptions (e.g., 404 Not Found) and directs the user to the/Errorpage.
csharp:TheExampleApp/Startup.cs
// In Configure method, inside the non-development block
else
{
// ... HTTPS enforcement rule
app.UseExceptionHandler("/Error");
}
// ...
app.UseStatusCodePagesWithReExecute("/Error");1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Performance Optimizations
The Dockerfile ensures that the application is published in Release mode, which enables compiler optimizations and disables debugging-specific code paths for better performance.
dockerfile:Dockerfile
RUN dotnet publish -c Release -o /app/1
Heroku
The application includes a specific Heroku environment configuration, primarily defined in the Dockerfile.
Heroku-specific Settings
The Dockerfile explicitly sets ASPNETCORE_ENVIRONMENT to Heroku.
dockerfile:Dockerfile
ENV ASPNETCORE_ENVIRONMENT=Heroku1
Platform Detection and Behavior
There is no custom IsHeroku() check in Startup.cs. Therefore, the Heroku environment behaves identically to the Production and Staging environments because the env.IsDevelopment() check evaluates to false.
This means that when deployed to Heroku, the application will automatically have:
- Production Error Handling: Uses
UseExceptionHandlerandUseStatusCodePagesWithReExecute. - HTTPS Enforcement: The
X-Forwarded-Protocheck is essential for Heroku's routing mesh, which terminates SSL before forwarding traffic to the application container.
For detailed instructions on deploying the application to this platform, see the Heroku Deployment Guide.