Search code examples
c#asp.netwebformsautofac

Autofac Webforms is there away to ignore postback dependency injection


I am maintaining companies very old website (WebForms) and it is using Autofac as Dependency Injection.

One of the issues I have is that every time Page_Load is called, any dependencies are resolved again setting them to new. How can I stop this?

Don't have code at hand right now but this example should explain better

Example case

public class DatabaseManager
{
    public string CustomerDbConnection {get;set;}
}

public partial class SiteSetup: Page
{
    public DatabaseManager dbManager {get;set;}

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
           // blah blah
        }

    }

    protected void DdlDatabase_SelectedIndexChanged(object sender, EventArgs e)
    {
        dbManager.CustomerDbConnection  = "Some db connection";
    }

    protected void ImageSaveSite_Click(object sender, EventArgs e)
    {
       // Do something with dbManager.CustomerDbConnection
    }
}

So in the above, DatabaseManager is injected into SiteSetup page. When the user selects an item in a dropdown list box 'DdlDatabase', the 'dbManager.CustomerDbConnection' is set.

If the user then clicks on a button, 'ImageSaveSite', then I get an exception when trying to access 'dbManager.CustomerDbConnection' because it is null.

Put a breakpoint in the 'Page_OnLoad' method and I can see every time it is called I can see 'dbManager.CustomerDbConnection' is null. I can only assume that a new instance of 'DatabaseManager' is being resolved.

Is there a way of preventing this? I was thinking about registering DatabaseManager as a singleton but then wouldn't every user of the website be accessing the same instance?


Solution

  • Because of how WebForms lifecycle works I recommend slightly different solution with use of ViewState

    If you want to have some communication between postbacks you need to persist it in ViewState. But connection is not serializable. So I used helper property ConnectionIdentifier for keeping selected Identifier.

    public string ConnectionIdentifier
    {
         get => ViewState[nameof(ConnectionIdentifier)] as string;
         set => ViewState[nameof(ConnectionIdentifier)] = value;
    }
    
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
           // blah blah
        }       
    }
    
    protected void DdlDatabase_SelectedIndexChanged(object sender, EventArgs e)
    {
        ConnectionIdentifier = "Selected db identifier";
    }
    
    protected void ImageSaveSite_Click(object sender, EventArgs e)
    {
        if(ConnectionIdentifier != null){
            //not really needed depending on your UI
    
            dbManager.CustomerDbConnection = ConnectionIdentifier; //processing identifier
        }
       
    }