Just curious about UserControls and Dependency Injections

Topics: Web Client Software Factory, User Forum
Jul 23, 2008 at 5:21 PM
I know that DI supports UserControls as of Oct 2007 release.

I am just curious how was that accomplished. I notice that DI occurs not when the control is loaded via Page.LoadControl() (assuming UC is loaded programmatically), but rather when the control is added to the Controls collection of whatever container is holding it. Does anybody know the internals and where the hook/event is that triggers the DI?

G.


Jul 23, 2008 at 7:05 PM
Edited Jul 23, 2008 at 7:06 PM
The user controls inherit from Microsoft.Practices.CompositeWeb.Web.UI.UserControl.  In the Init event, it calls WebClientApplication.BuildItemWithCurrentContext(this);

public class UserControl : UserControl
{
    // Methods
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        WebClientApplication.BuildItemWithCurrentContext(this);
    }
}

You must ensure your user control has finished the OnInit before accessing injected dependencies.
Jul 24, 2008 at 9:44 PM
The reason for this approach was outlined a while back in a blog post I did: Breaking Changes in the Composite Web Application Block and the there was a little clarification in Clarification on Changes in CWAB's Dependency Injection.  These posts explain the reasons it has to be this way, and not true DI earlier in the Page/UserControl lifecycle.

More recently, Chris and I played with Unity outside of WCSF and got something to work with Proof of Concept: a simple DI solution for ASP.NET WebForms.  This little proof of concept may simplify later versions of CWAB and WCSF.

I hope this helps a bit,
Michael Puleio -- patterns & practices
http://blogs.msdn.com/mpuleio  
Jul 25, 2008 at 3:31 PM
I appreciate both your answers!

While my original question was just out of pure curiosity and before I even noticed that you've extended the base UserControl class, our little team has an issue that surfaced after we upgraded to Oct 2007 release
(I have done my 1-hour limited research and moving forward with using your helper and ask for Injection, but I figured I'd ask anyway)

Our problem seems to be a post-back event handler that tries to use an AJAXcontrollToolkit tab before that tab has been created. Here's our July 2007 version of the code (we were forcing DI on UC during Page.LoadControl in an extended CompositeWeb.WebClientApplication)

//in the View
Page_Load() {
    If Is NOT A Postback: {_presenter.OnViewInitialized()}

    //page-wide object - initialize - will host individual tabs, each of which displays one Usercontrol
    _ajaxTabcontainer = new AjaxControlToolkit.TabContainer();

    _presenter..OnViewLoaded(); {which does the following: 
                                                    1. Prepare business object; 
                                                    2. Call View.ShowBO(); 
                                                    3. The View loads the UserControl (DI-ed) that displays the BO 
                                                    4. new AjaxControlToolkit.TabPanel() that hosts the UC
                                                    5. Add TabPanel to the _ajaxTabcontainer;}

    //at this point each UC is on it's own tab, all tabs are added to _ajaxTabcontainer
    //display the _ajaxTabcontainer on the .ASPX page
    PlaceHolder1.Controls.Add(_ajaxTabcontainer);

Upgrading to Oct 2007 broke this solution because it is the last line PlaceHolder1.Controls.Add that triggers the DI, which is too late

Moving PlaceHolder1.Controls.Add call earlier, before _presenter..OnViewLoaded(), causes the problem I mentioned earlier with the missing AJAX tab during post-back

We are really time-pressed and neither can redesign nor invest much more time in getting this right-er, but if someone can point out something - it would be of great help!
Jul 25, 2008 at 3:33 PM
Edited Jul 25, 2008 at 3:49 PM
... actually I am wondering what will happen when I trigger DI on a UserControl before its OnInit and then one more time later, when the OnInit itself triggers a DI?

Addition: The secoond DI runs as well (of course it does). We're rolling back to our initial solution to trigger the DI during LoadControl