Why does everyone say dependency injection in ASP.NET webforms is hard when PageHandlerFactory and IHttpHandlerFactory exist? Why does everyone say dependency injection in ASP.NET webforms is hard when PageHandlerFactory and IHttpHandlerFactory exist? asp.net asp.net

Why does everyone say dependency injection in ASP.NET webforms is hard when PageHandlerFactory and IHttpHandlerFactory exist?


Because of the way ASP.NET is designed, Page classes need to have a default constructor. When you want to use constructor injection, there is a way around this. You can make the default constructor protected and add a single public constructor that takes the dependencies as follows:

public partial class _Default : System.Web.UI.Page{    private IUserService service;    protected _Default()    {    }    public _Default(IUserService service)    {        this.service = service;    }}

This allows you to create a custom PageHandlerFactory and inject the dependencies in the constructor.

So this works, but there is a catch though. The _Default class you define is not the actual class ASP.NET uses. ASP.NET creates a new class that inherits from _Default. This new class builds a control hierarchy based on the markup in the .aspx file. This class looks a bit like this:

public class ASPGeneratedDefault : _Default{    public ASPGeneratedDefault() : base()    {    }     protected override void OnPreInit(object s, EventArgs e)     {          // Building up control hierarchy.     }}

As you can see, the custom constructor hasn't been overridden in the ASPGeneratedDefault by ASP.NET. Because of this there is no way of letting a DI framework create this type for us. The way around this is to let ASP.NET create this type for us and invoke the non-default constructor of the _Default base class on that existing instance. Because this instance already exists, we must do this with reflection and this will fail when run in partial trust.

Besides that, this works for page classes, but not for user controls on the page. The code generator of ASP.NET news up those controls with their default constructor during the control hierarchy build up process. When you want this to work for them, you need your custom PageHandlerFactory to hook to the PreInit event of those controls, because during the time the page class is constructed, the related controls and user controls are not yet created. However, to register the PreInit event on them, you need to find those controls within the page class, and again we need to reflect over the page class. Because controls are stored in non-public instance fields, again this won't work in partial trust.

Whether or not it is a problem your application can not run in partial trust is up to you, but since the security model of .NET 4 has been simplified considerably, it is very easy to run web apps in partial trust and it is something I strive to do.

TLDR; So in conclusion, it is possible to do so (see for instance this example), but because of the limitations of the ASP.NET Web Forms framework, you need to run in full trust to get it to work.

UPDATE Microsoft has obsoleted partial trust for ASP.NET starting with NET 4.0 (read here). So from that point of view, keeping away from full trust might not be that useful (you'll need it anyway).