├── .gitignore ├── DI.WebForms.sln ├── readme.md ├── sample └── DI.WebForms.Sample │ ├── DI.WebForms.Sample.csproj │ ├── Dependency.cs │ ├── Global.asax │ ├── Global.asax.cs │ ├── Index.aspx │ ├── Index.aspx.cs │ ├── Index.aspx.designer.cs │ ├── Main.Master │ ├── Main.Master.cs │ ├── Main.Master.designer.cs │ ├── Properties │ └── AssemblyInfo.cs │ └── Web.config └── src └── DI.WebForms ├── DI.WebForms.csproj └── ServiceProvider.cs /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | *.user 3 | bin/ 4 | obj/ 5 | -------------------------------------------------------------------------------- /DI.WebForms.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27520.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DI.WebForms", "src\DI.WebForms\DI.WebForms.csproj", "{17767851-7333-4B9A-83F9-3D95EA5801C7}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DI.WebForms.Sample", "sample\DI.WebForms.Sample\DI.WebForms.Sample.csproj", "{69CEDC80-3724-4E74-8F8A-6B7322080562}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {17767851-7333-4B9A-83F9-3D95EA5801C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {17767851-7333-4B9A-83F9-3D95EA5801C7}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {17767851-7333-4B9A-83F9-3D95EA5801C7}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {17767851-7333-4B9A-83F9-3D95EA5801C7}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {69CEDC80-3724-4E74-8F8A-6B7322080562}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {69CEDC80-3724-4E74-8F8A-6B7322080562}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {69CEDC80-3724-4E74-8F8A-6B7322080562}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {69CEDC80-3724-4E74-8F8A-6B7322080562}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {A7C990D9-FFBE-44F9-A4DD-40F17EC61837} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Starting with .NET 4.7.2 ([released April, 30st](https://devblogs.microsoft.com/dotnet/announcing-the-net-framework-4-7-2/), 2 | Microsoft offers an endpoint to plug our favorite dependency injection container when developing ASP.Net Webforms applications 3 | , making possible to inject dependencies into UserControls, Pages and MasterPages. 4 | 5 | See blog post: [USING ASP.NET WEBFORM DEPENDENCY INJECTION WITH .NET 4.7.2](https://www.natmarchand.fr/aspnet-dependency-injection-net472/) for addtional details -------------------------------------------------------------------------------- /sample/DI.WebForms.Sample/DI.WebForms.Sample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 7 | 8 | 2.0 9 | {69CEDC80-3724-4E74-8F8A-6B7322080562} 10 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 11 | Library 12 | Properties 13 | Microsoft.Extensions.DependencyInjection.WebForms.Sample 14 | Microsoft.Extensions.DependencyInjection.WebForms.Sample 15 | v4.7.2 16 | true 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | true 28 | full 29 | false 30 | bin\ 31 | DEBUG;TRACE 32 | prompt 33 | 4 34 | 35 | 36 | true 37 | pdbonly 38 | true 39 | bin\ 40 | TRACE 41 | prompt 42 | 4 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 2.0.0 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | Global.asax 66 | 67 | 68 | Index.aspx 69 | ASPXCodeBehind 70 | 71 | 72 | Index.aspx 73 | 74 | 75 | Main.Master 76 | ASPXCodeBehind 77 | 78 | 79 | Main.Master 80 | 81 | 82 | 83 | 84 | 85 | {17767851-7333-4b9a-83f9-3d95ea5801c7} 86 | DI.WebForms 87 | 88 | 89 | 90 | 10.0 91 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | False 101 | True 102 | 53931 103 | / 104 | http://localhost:53931/ 105 | False 106 | False 107 | 108 | 109 | False 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /sample/DI.WebForms.Sample/Dependency.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Globalization; 4 | using System.Threading; 5 | 6 | namespace Microsoft.Extensions.DependencyInjection.WebForms.Sample 7 | { 8 | [DebuggerDisplay("Dependency #{" + nameof(Id) + "}")] 9 | public class Dependency : IDependency 10 | { 11 | private static int _id; 12 | 13 | public int Id { get; } 14 | 15 | public Dependency() 16 | { 17 | Id = Interlocked.Increment(ref _id); 18 | } 19 | 20 | public string GetFormattedTime() => DateTimeOffset.UtcNow.ToString("f", CultureInfo.InvariantCulture); 21 | } 22 | 23 | public interface IDependency 24 | { 25 | int Id { get; } 26 | string GetFormattedTime(); 27 | } 28 | } -------------------------------------------------------------------------------- /sample/DI.WebForms.Sample/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="Autofac.Integration.Web.Sample.Global" Language="C#" %> 2 | -------------------------------------------------------------------------------- /sample/DI.WebForms.Sample/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web; 3 | 4 | namespace Microsoft.Extensions.DependencyInjection.WebForms.Sample 5 | { 6 | public class Global : HttpApplication 7 | { 8 | protected void Application_Start(object sender, EventArgs e) 9 | { 10 | var collection = new ServiceCollection(); 11 | collection.AddScoped(); 12 | var provider = new ServiceProvider(collection.BuildServiceProvider()); 13 | HttpRuntime.WebObjectActivator = provider; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /sample/DI.WebForms.Sample/Index.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Title="" Language="C#" MasterPageFile="~/Main.Master" CodeBehind="Index.aspx.cs" Inherits="Autofac.Integration.Web.Sample.Index" %> 2 | 3 | 4 | 5 | 6 |

Hi from Index

7 |
<%=Dependency.GetFormattedTime() %>
8 |
Dependency #<%=Dependency.Id %>
9 |
10 | -------------------------------------------------------------------------------- /sample/DI.WebForms.Sample/Index.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web.UI; 3 | 4 | namespace Microsoft.Extensions.DependencyInjection.WebForms.Sample 5 | { 6 | public partial class Index : Page 7 | { 8 | protected IDependency Dependency { get; } 9 | 10 | public Index(IDependency dependency) 11 | { 12 | Dependency = dependency; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /sample/DI.WebForms.Sample/Index.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | using System; 11 | 12 | namespace Microsoft.Extensions.DependencyInjection.WebForms.Sample { 13 | 14 | 15 | public partial class Index { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /sample/DI.WebForms.Sample/Main.Master: -------------------------------------------------------------------------------- 1 | <%@ Master Language="C#" CodeBehind="Main.master.cs" Inherits="Autofac.Integration.Web.Sample.Main" %> 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 | 15 | 16 |
17 |
<%=Dependency.GetFormattedTime() %>
18 |
Dependency #<%=Dependency.Id %>
19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /sample/DI.WebForms.Sample/Main.Master.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web.UI; 3 | 4 | namespace Microsoft.Extensions.DependencyInjection.WebForms.Sample 5 | { 6 | public partial class Main : MasterPage 7 | { 8 | protected IDependency Dependency { get; } 9 | 10 | public Main(IDependency dependency) 11 | { 12 | Dependency = dependency; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /sample/DI.WebForms.Sample/Main.Master.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | using System; 11 | 12 | namespace Microsoft.Extensions.DependencyInjection.WebForms.Sample { 13 | 14 | 15 | public partial class Main { 16 | 17 | /// 18 | /// HeaderPlaceHolder control. 19 | /// 20 | /// 21 | /// Auto-generated field. 22 | /// To modify move field declaration from designer file to code-behind file. 23 | /// 24 | protected global::System.Web.UI.WebControls.ContentPlaceHolder HeaderPlaceHolder; 25 | 26 | /// 27 | /// form1 control. 28 | /// 29 | /// 30 | /// Auto-generated field. 31 | /// To modify move field declaration from designer file to code-behind file. 32 | /// 33 | protected global::System.Web.UI.HtmlControls.HtmlForm form1; 34 | 35 | /// 36 | /// ContentPlaceHolder control. 37 | /// 38 | /// 39 | /// Auto-generated field. 40 | /// To modify move field declaration from designer file to code-behind file. 41 | /// 42 | protected global::System.Web.UI.WebControls.ContentPlaceHolder ContentPlaceHolder; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /sample/DI.WebForms.Sample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Microsoft.Extensions.DependencyInjection.WebForms.Sample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Microsoft.Extensions.DependencyInjection.WebForms")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("69cedc80-3724-4e74-8f8a-6b7322080562")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /sample/DI.WebForms.Sample/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/DI.WebForms/DI.WebForms.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472 5 | pdbonly 6 | True 7 | Microsoft.Extensions.DependencyInjection.WebForms 8 | Microsoft.Extensions.DependencyInjection.WebForms 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/DI.WebForms/ServiceProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Web; 4 | 5 | namespace Microsoft.Extensions.DependencyInjection.WebForms 6 | { 7 | public class ServiceProvider : IServiceProvider 8 | { 9 | private readonly IServiceProvider _serviceProvider; 10 | 11 | public ServiceProvider(IServiceProvider serviceProvider) 12 | { 13 | _serviceProvider = serviceProvider; 14 | } 15 | 16 | public object GetService(Type serviceType) 17 | { 18 | try 19 | { 20 | IServiceScope lifetimeScope; 21 | var currentHttpContext = HttpContext.Current; 22 | if (currentHttpContext != null) 23 | { 24 | lifetimeScope = (IServiceScope)currentHttpContext.Items[typeof(IServiceScope)]; 25 | if (lifetimeScope == null) 26 | { 27 | void CleanScope(object sender, EventArgs args) 28 | { 29 | if (sender is HttpApplication application) 30 | { 31 | application.RequestCompleted -= CleanScope; 32 | lifetimeScope.Dispose(); 33 | } 34 | } 35 | 36 | lifetimeScope = _serviceProvider.CreateScope(); 37 | currentHttpContext.Items.Add(typeof(IServiceScope), lifetimeScope); 38 | currentHttpContext.ApplicationInstance.RequestCompleted += CleanScope; 39 | } 40 | } 41 | else 42 | { 43 | lifetimeScope = _serviceProvider.CreateScope(); 44 | } 45 | 46 | return ActivatorUtilities.GetServiceOrCreateInstance(lifetimeScope.ServiceProvider, serviceType); 47 | } 48 | catch (InvalidOperationException) 49 | { 50 | //No public ctor available, revert to a private/internal one 51 | return Activator.CreateInstance(serviceType, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, null, null); 52 | } 53 | } 54 | } 55 | } 56 | --------------------------------------------------------------------------------