I've noticed a strange behavior for ASPNETCORE_ENVIRONMENT
- when i set it to
Development, my application fails (as it should) due to some services' incorrect lifetimes (akacannot consume scoped service...) - when i set it to
Local(we useLocalfor local development; we useDevelopmentfor the develop env where our frontend works), the application works just fine, no errors are thrown, scoped services are consumed by singleton services...
Is there a way to preserve the behavior of the Development in the Local and other environments? The issue is that I was completely unaware that I was pushing invalid code (cross-checking tens of services isn't an easy task - that's why I assumed that it was done by my app locally).
Also - I tried to pin the line where this additional Development-specific logic is implemented but with no luck. Maybe there's someone here who knows the place - I'd really like to spend a short while reading the code.
I created a minimal reproducible example:
Program.cs
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using WebApplication1;
var builder = Host.CreateDefaultBuilder(args)
.ConfigureHostConfiguration(configHost =>
{
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
builder.Build().Run();
Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using WebApplication1.Services;
namespace WebApplication1
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services
.AddControllers();
services
.AddSingleton<SingletonService>()
.AddScoped<ScopedService>();
}
public void Configure(IApplicationBuilder app)
{
app
.UseRouting();
app.ApplicationServices
.GetService<SingletonService>()
.DoSth();
}
}
}
SingletonService
using System;
namespace WebApplication1.Services;
public class SingletonService
{
private readonly ScopedService _scopedService;
public SingletonService(ScopedService scopedService)
{
_scopedService = scopedService;
}
public void DoSth()
{
Console.WriteLine($"{nameof(SingletonService)} - {nameof(DoSth)}");
_scopedService.DoSth();
}
}
ScopedService.cs
using System;
namespace WebApplication1.Services;
public class ScopedService
{
public void DoSth()
{
Console.WriteLine($"{nameof(ScopedService)} - {nameof(DoSth)}");
}
}
launchSettings.json
{
"profiles": {
"WebApplication1": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:8080",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
When you create the default
IHostBuilderusingHost.CreateDefaultBuilder, it will set service Scope and Building validation totruewhen the Environment is "Development". The following is relevant bit of code taken from dotnet's source code:You can navigate the source code starting with Host.CreateDefaultBuilder and ending with HostingHostBuilderExtensions.CreateDefaultServiceProviderOptions.