Friday, June 18, 2010

Lingering Event Handlers in ASP.NET Web Forms

I hate dealing with dynamically added user controls. Whenever you add multiple user controls to your page through the Controls.Add mechanism, the order of events becomes a great big mess to handle. There are tons of articles around the web that try to explain how you can alleviate some of these issues. But I'm convinced that unless you were on the team that built ASP.NET Web Forms, it's impossible to understand these issues completely.

I'm here to talk about one issue in particular I came across last night and solved today. It relates to custom events. If your parent page has a button on it that you want to be intercepted by a child control, then it can be done something like this:

Parent Page
Private Sub btnSave_Click() Handles btnSave.Click
  CurrentWebsiteApp.OnSavePage() ' Custom function that raises a custom SavePageEvent
End Sub

Dynamically added user control
Private Sub Page_Init() Handles Me.Init
  RemoveHandler CurrentWebsiteApp.SavePageEvent, AddressOf SaveMe
  AddHandler CurrentWebsiteApp.SavePageEvent, AddressOf SaveMe
End Sub

Private Sub SaveMe()
  ' Save some stuff
End Sub

And this works. However, what I discovered is that even after this user control is disposed the event handler persists for the user's session. And if you have this same set up on dozens of dynamic user controls throughout your website then the SaveMe() function might be called on user controls that are no longer a part of the page. Craziness, I know.

The solution I found is to do this in your user control:

Public Overrides Sub Dispose()
  RemoveHandler CurrentWebsiteApp.SavePageEvent, AddressOf SaveMe
  MyBase.Dispose()
End Sub

This will reliably remove the handler for this control when the control is disposed. This effectively prevents the handler from lingering on. Problem solved!

0 comments: