ASP.NET Annoyances with Dynamic Controls

I really DO like ASP.NET ... but there are a few things that have really been driving me nuts. In this case, it's creating dynamic controls.

I'm currently building a web application to check email accounts. Each message generates a new checkbox dynamically, allowing the user to delete the message. The first limitation of dynamically created controls in this context is that they must be created in the Page_Load or On_Init events to participate in viewstate. That makes sense, or at least is reasonable; the problem is, well, let's walk through the order of events (no pun intended):

1. User logs in.
2. Email is collected into a Mailstore object that contains a collection of messages.
3. Messages displayed to user; each message contains a checkbox to delete the message.
4. On postback, we need to check each message's checkbox. If it's checked, flag a property in the Message object to ToBeDeleted.
5. Reconnect to POP mailserver, checking for new messages and deleting flagged messages.
6. Go to step 2.

The problem here lies in step 4. First, to check the state of the checkbox, we need to recreate the checkbox and simply read its value. It seems somewhat silly to recreate the checkbox only to read its value and then simply delete it, but I digress.

It would be really cool if we could simply wire up the event handler every time we create a checkbox to check the state when it's changed. Something like:

foreach (Message msg in MailStore.Messages) {
    CheckBox cb = new CheckBox();
    cb.CheckedChanged += new System.EventHandler(this.CheckBox_Checked);
    cb.Id = msg.Guid.ToString();
}


Because we're assigning the Id of control to the message's Guid, it's easy to cross reference. In the event handler, we can mark it as such:

private void CheckBox_Checked(object sender, EventArgs e) {

    Checkbox cb = (CheckBox)sender;
    if (cb.Checked)
        Mailstore.MarkMessageForDeletion((Guid)cb.Id);
}


Straightforward stuff, simply letting the Mailstore worry about its message collection. The next time it connects to the POP server, it will delete flagged messages.

The problem that were facing here is both performance (round trips to the POP server) and ASP.NET limitation. I can't wait until the event fires to find out if I need to delete the message. This is because I need to have a current Mailstore collection no later than the Page_Load because these checkbox controls require viewstate ... and this event would get fired afterwards. Any other way to do this would require that controls either don't participate in viewstate, create a lot of extra controls we don't really need, or we make multiple calls to the POP server. None of these options seem all that ideal if want to stay within the ASP.NET paradigm.

The ideal solution would be to use an event like above to flag the messages, then afterwards reconnect to the POP server, download the new mail while deleting flagged messages. Finally, create the checkboxes and display all current messages (but as we've already established, we can't do this).

So I had to cut a few corners. If we want to stick everything in the Page_Load, it is messy, and creates unnecessary overhead with the checkboxes for the sole purpose of not showing them (remember, they're deleted items.

Ultimately, the most sound approach was to rely on the Forms collection. With a simple loop, it's easy to check each form element type (ie if it's a checkbox) and then simply read its "on" state. Something like this in the OnInit or Page_Load:

foreach (MailMessage msg in Mailstore.Messages)
{
    if (Request.Form[msg.MessageGuid.ToString()] != null &&
    Request.Form[msg.MessageGuid.ToString()].ToLower() == "on")
    {
        MailStore.MarkForDeletion(Mailstore, msg.MessageGuid);    
    }
}


So that's what I've ended up doing after hours of frustration. I hate doing it this way -- but it is the most performant and the least amount of code.

If you can recommend something better, drop me some feedback! I'd like to try it.
Comments are closed

My Apps

Dark Skies Astrophotography Journal Vol 1 Explore The Moon
Mars Explorer Moons of Jupiter Messier Object Explorer
Brew Finder Earthquake Explorer Venus Explorer  

My Worldmap

Month List