This is the case if you register a type, say
MySingleton
, when configuring the web host …
WebHost
.CreateDefaultBuilder()
.UseStartup()
.ConfigureServices(services => services.AddSingleton())
.Build()
.Run();
…, e.g. so that is available in the constructor of your Startup
public class Startup
{
private readonly MySingleton _mySingletonFromHostingServiceProvider;
public Startup(MySingleton mySingletonFromHostingServiceProvider)
{
_mySingletonFromHostingServiceProvider = mySingletonFromHostingServiceProvider;
}
...
}
Now, if we resolve MySingleton
during normal web request we get a whole new instance instead the same instance as in constructor of the Startup
class.
public void Configure(IApplicationBuilder app)
{
app.Use((ctx, next) =>
{
var mySingleton = ctx.RequestServices.GetRequiredService();
// the comparison of 2 instances yields "false"
var areEqual = _mySingletonFromHostingServiceProvider == mySingleton;
Console.WriteLine($"==> {nameof(_mySingletonFromHostingServiceProvider)} == {nameof(mySingleton)}: {areEqual}");
return next();
});
}
There are at least two ways to fix this problem.
Either pass an instance of MySingleton
to method AddSingleton
instead of passing just the type
var mySingleton = new MySingleton();
WebHost
.CreateDefaultBuilder()
.UseStartup()
.ConfigureServices(services => services.AddSingleton(mySingleton))
.Build()
.Run();
or by replacing the previous registration with a new one in ConfigureServices
public class Startup
{
private readonly MySingleton _mySingletonFromHostingServiceProvider;
public Startup(MySingleton mySingletonFromHostingServiceProvider)
{
_mySingletonFromHostingServiceProvider = mySingletonFromHostingServiceProvider;
}
public void ConfigureServices(IServiceCollection services)
{
services.Replace(new ServiceDescriptor(typeof(MySingleton), _mySingletonFromHostingServiceProvider));
// alternative way
//services.AddSingleton(_mySingletonFromHostingServiceProvider);
}
...
}
According to @davidfowl the ASP.NET team will address this problem in the future.
PS: There is at least another one solution to fix this problem and gaining back the control over your web app but that’s for another time … 🙂