Constructor-based dependency injection in ASP.NET Web Forms (introduced in .NET Framework 4.7.2) doesn't work.
The reason is that BinaryCompatibility.Current.TargetsAtLeastFramework472 is false here:
|
if (BinaryCompatibility.Current.TargetsAtLeastFramework472 && |
This is because there is a bug in .NET Framework but it was hidden by App Domains, but WebFormsForCore doesn't use App Domains.
Look at System.Web.Hosting.ApplicationManager.CreateAppDomainWithHostingEnvironment:
Here we first time initialize ApplicationData, but there is no TargetFrameworkKey yet (appDomainAdditionalData is empty):
|
SetApplicationData(bindings, appDomainAdditionalData, AssemblyLoadContext.Default, AppDomain.CurrentDomain); |
It will be calculated but not yet added to ApplicationData here:
|
appDomainAdditionalData[System.Web.Util.BinaryCompatibility.TargetFrameworkKey] = targetFrameworkName; |
Then some strange code here that breaks everything:
|
requireHostExecutionContextManager = new System.Web.Util.BinaryCompatibility(targetFrameworkName).TargetsAtLeastFramework45 ? true : false; |
It is because there is implicit call to System.Web.Util.BinaryCompatibility's static constructor:
|
var targetFramework = ApplicationManager.GetLoadContextData(TargetFrameworkKey) as FrameworkName; |
And since there is no TargetFrameworkKey in ApplicationData - System.Web.Util.BinaryCompatibility.Current became .NET Framework 4.0 (VersionUtil.FrameworkDefault)! And now BinaryCompatibility.Current.TargetsAtLeastFramework472 everytime will return false!
At last TargetFrameworkKey is added to ApplicationData, but it is too late:
|
SetApplicationData(bindings, appDomainAdditionalData, appContext, appDomain); |
As I said .NET Framework also has this bug. BUT! Here:
|
env.Initialize(this, appHost, configMapPathFactory, hostingParameters, policyLevel); |
System.Web.dll!System.Web.Hosting.HostingEnvironment.Initialize is called in another AppDomain, and later it calls System.Web.Util.BinaryCompatibility's static constructor again! And that time ApplicationData already has TargetFrameworkKey and BinaryCompatibility.Current.TargetsAtLeastFramework472 is true.
But WebFormsForCore doesn't use App Domains and doesn't call static constructor again.
Constructor-based dependency injection in ASP.NET Web Forms (introduced in .NET Framework 4.7.2) doesn't work.
The reason is that
BinaryCompatibility.Current.TargetsAtLeastFramework472isfalsehere:WebFormsForCore/src/WebFormsForCore.Web/Compilation/TemplateControlCodeDomTreeGenerator.cs
Line 276 in 8fdf232
This is because there is a bug in .NET Framework but it was hidden by App Domains, but WebFormsForCore doesn't use App Domains.
Look at
System.Web.Hosting.ApplicationManager.CreateAppDomainWithHostingEnvironment:Here we first time initialize ApplicationData, but there is no
TargetFrameworkKeyyet (appDomainAdditionalDatais empty):WebFormsForCore/src/WebFormsForCore.Web/Hosting/ApplicationManager.Core.cs
Line 1059 in 8fdf232
It will be calculated but not yet added to ApplicationData here:
WebFormsForCore/src/WebFormsForCore.Web/Hosting/ApplicationManager.Core.cs
Line 1116 in 8fdf232
Then some strange code here that breaks everything:
WebFormsForCore/src/WebFormsForCore.Web/Hosting/ApplicationManager.Core.cs
Line 1137 in 8fdf232
It is because there is implicit call to
System.Web.Util.BinaryCompatibility's static constructor:WebFormsForCore/src/WebFormsForCore.Web/Util/BinaryCompatibility.cs
Line 26 in 8fdf232
And since there is no
TargetFrameworkKeyinApplicationData-System.Web.Util.BinaryCompatibility.Currentbecame .NET Framework 4.0 (VersionUtil.FrameworkDefault)! And nowBinaryCompatibility.Current.TargetsAtLeastFramework472everytime will returnfalse!At last
TargetFrameworkKeyis added to ApplicationData, but it is too late:WebFormsForCore/src/WebFormsForCore.Web/Hosting/ApplicationManager.Core.cs
Line 1357 in 8fdf232
As I said .NET Framework also has this bug. BUT! Here:
WebFormsForCore/src/WebFormsForCore.Web/Hosting/ApplicationManager.Core.cs
Line 1471 in 8fdf232
System.Web.dll!System.Web.Hosting.HostingEnvironment.Initializeis called in another AppDomain, and later it callsSystem.Web.Util.BinaryCompatibility's static constructor again! And that time ApplicationData already hasTargetFrameworkKeyandBinaryCompatibility.Current.TargetsAtLeastFramework472istrue.But WebFormsForCore doesn't use App Domains and doesn't call static constructor again.