CreateChildControls before LoadViewState = Bug in DataGrid and Repeater


F

Ferret

I've found what seems to be a nasty bug in the DataGrid and Repeater
classes. If CreateChildControls gets called before LoadViewState,
ViewState fails to map and you end up with nothing on a Postback.
Please try the following test, and let me know if you can reproduce
this:

- Create a custom DataGrid or Repeater class that does nothing but
derive from one of the above and gives a place to put breakpoints in
overriden handlers
- Create a simple test case on a WebForm. I use template columns, but
BoundColumns might work as well.
- Create something in your DataGrid/Repeater that posts back, like a
LinkButton in a HeaderTemplate.
- Only DataBind if it's not a PostBack
- Put an EnsureChildControls at the beginning of OnInit in your custom
DataGrid/Repeater

When I click on the LinkButton, I get no output at all. Put
breakpoints in OnInit, LoadViewState, and CreateChildControls of your
custom class. If CreateChildControls gets called before LoadViewState,
nothing maps and there's no output. Now, if you take
EnsureChildControls out of OnInit, and your test is simple, you'll see
LoadViewState happen before CreateChildControls and everything will
work wonderfully.

Why is that? That's exactly opposite from everything I've learned so
far concerning server controls. Usually, the earlier you re-create all
your controls the better for mapping events, ViewState, etc. Why are
these framework controls different? I can't avoid having my controls
created early in my big application because I usually put
EnsureChildControls in all my Properties, etc, like I thought was good
practice. Are DataGrids and Repeaters doomed to fail with these
practices?

I've considered finding a workaround. I even considered calling
LoadViewState at the beginning of CreateChildControls on a PostBack,
but I haven't tried it yet because I don't know if it would be safe to
do it even if it's possible. Any help or input on why this is
happening or any hacks or workarounds will be very welcome.
 
Ad

Advertisements

F

Ferret

Microsoft finally admitted this is a bug and refunded the cost of my
support ticket. They did not, however tell me a better way to solve it,
so I'm still using my solution (that I recently found on my own) in my
custom Repeater without any problems so far. Here is my solution that
you need in your custom Repeater or DataGrid:

protected override void LoadViewState(object savedState)
{
base.LoadViewState (savedState);

// If our child controls have already been created, we need to call

// CreateControlHierarchy to give them a chance to bind from
// ViewState. This is the bug I've found in the Repeater and
DataGrid.
if (ChildControlsCreated)
CreateControlHierarchy(false); // builds templates and binds
from ViewState
}

The normal sequence of events is OnInit, LoadViewState, then OnLoad.
If CreateChildControls gets called in OnInit (very common and even
best-practice in most controls) on the Repeater or DataGrid during a
PostBack, it will NOT populate from ViewState.

Once again, this may fix a ton of "mysterious" issues with ASP.NET's
templated databound controls. The "DataGrid disappears" bug, some
"events not firing in DataGrid" bugs, etc. It is a rare occurence
though because CreateChildControls doesn't USUALLY get called on these
controls before the LoadViewState event. When making your own custom
controls, however, MS is very clear to point out that
CreateChildControls can get called "at any point in the control's
lifecyle", and you should definitely be able to handle it happening at
any point. I call mine in OnInit of pretty much all my custom controls
to prevent any timing-related bugs. MS just needs to read their own
docs.

Here is the MS response:

"Our developer has confirmed that it is a product issue. They are now
working on this problem, and it seems that there is no fix at this
time. I have forwarded your solution to them, and I will contact you if
there is any further update.

Our developer doesn't see any potential issues with your solutions. But
there may be issues under complex scenarios which is hard to predict
now. The best suggestion from them is to avoid calling
EnsureChildControls before the Viewstate is loaded."
 
F

Ferret

Microsoft finally admitted this is a bug and refunded the cost of my
support ticket. They did not, however tell me a better way to solve it,
so I'm still using my solution (that I recently found on my own) in my
custom Repeater without any problems so far. Here is my solution that
you need in your custom Repeater or DataGrid:

protected override void LoadViewState(object savedState)
{
base.LoadViewState (savedState);

// If our child controls have already been created, we need to call

// CreateControlHierarchy to give them a chance to bind from
// ViewState. This is the bug I've found in the Repeater and
DataGrid.
if (ChildControlsCreated)
CreateControlHierarchy(false); // builds templates and binds
from ViewState
}

The normal sequence of events is OnInit, LoadViewState, then OnLoad.
If CreateChildControls gets called in OnInit (very common and even
best-practice in most controls) on the Repeater or DataGrid during a
PostBack, it will NOT populate from ViewState.

Once again, this may fix a ton of "mysterious" issues with ASP.NET's
templated databound controls. The "DataGrid disappears" bug, some
"events not firing in DataGrid" bugs, etc. It is a rare occurence
though because CreateChildControls doesn't USUALLY get called on these
controls before the LoadViewState event. When making your own custom
controls, however, MS is very clear to point out that
CreateChildControls can get called "at any point in the control's
lifecyle", and you should definitely be able to handle it happening at
any point. I call mine in OnInit of pretty much all my custom controls
to prevent any timing-related bugs. MS just needs to read their own
docs.

Here is the MS response:

"Our developer has confirmed that it is a product issue. They are now
working on this problem, and it seems that there is no fix at this
time. I have forwarded your solution to them, and I will contact you if
there is any further update.

Our developer doesn't see any potential issues with your solutions. But
there may be issues under complex scenarios which is hard to predict
now. The best suggestion from them is to avoid calling
EnsureChildControls before the Viewstate is loaded."
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top