I recently discovered a logic bug in the Polls module. I searched around and, interestingly enough, did not find this discussed anywhere.
You can reproduce the bug by doing the following:
- Log in as an admin, and go to Admin/ManagePolls.aspx.
- Make a note of which is the Current poll (green checkmark in the polls Gridview). Click on its pencil as if you were going to edit it. Note that it is marked IsCurrent in the poll DetailsView. Click Cancel to cancel the edit.
- Go back up to the polls Gridview, and click to edit any poll which is NOT the current poll. Go down to the poll DetailsView, click the IsCurrent checkbox to mark it as the Current poll, and then click Update. Note that the green checkmark in the poll Gridview changes to the poll you just updated.
- Now, click to edit the poll that WAS the most recently current poll (the first poll you looked at). You will note that in the poll DetailsView, IsCurrent is checked, even though this is not the current poll!
- If you have several polls, you can click around in the polls Gridview, making different polls the Current poll. As you continue to do this, you will notice that any poll that was ever made Current will still be erroneously marked IsCurrent in the poll DetailsView.
Now, why is this happening? After a couple of hours of head-scratching, I figured it out, and thought Iâd share it with everybody.
First off, note that if you set enableCaching="false" in web.config, the bug goes away. So, obviously, itâs a problem with the caching. More precisely, as it turns out, itâs a problem with the purging of the cache.
Look at the UpdatePoll method in MB.TheBeerHouse.BLL.Polls.Poll. This is the method that fires when you update a poll in the poll Detailsview:
public static bool UpdatePoll(int id, string questionText, bool isCurrent)
{
PollDetails record = new PollDetails(id, DateTime.Now, "", questionText, isCurrent, false, DateTime.Now, 0);
bool ret = SiteProvider.Polls.UpdatePoll(record);
BizObject.PurgeCacheItems("Polls_Polls_true");
BizObject.PurgeCacheItems("Polls_Poll_" + id.ToString());
if (isCurrent)
BizObject.PurgeCacheItems("Polls_Poll_Current");
return ret;
}
Note what is getting purged from the cache here. It purges the list of active polls, the poll that youâre updating, and if you are setting this as the Current poll, the ID of the current poll. You should however note that is does NOT purge the poll that was current BEFORE this update was performed -- in other words, the poll that you are now making âun-Currentâ, so to speak.
When you edit a poll, the poll DetailsView uses the GetPollByID method to retrieve the poll to edit -- looking in the Cache first, of course. But because the poll that was before marked IsCurrent is never purged, the data in the Cache is stale, and the poll DetailsView therefore displays the wrong information.
The bottom line is, if you are setting a poll as the Current poll in the update, it is not enough to merely purge the ID of the current poll.
You need to purge the actual poll that you are making âun-Currentâ as well. Note the changes in the method below that fix this bug:
public static bool UpdatePoll(int id, string questionText, bool isCurrent)
{
PollDetails record = new PollDetails(id, DateTime.Now, "", questionText, isCurrent, false, DateTime.Now, 0);
int currPollID = Poll.CurrentPollID; //added
bool ret = SiteProvider.Polls.UpdatePoll(record);
Poll.PurgeCacheItems("Polls_Polls_true");
Poll.PurgeCacheItems("Polls_Poll_" + id.ToString());
if (isCurrent)
{
Poll.PurgeCacheItems("Polls_Poll_Current");
Poll.PurgeCacheItems("Polls_Poll_" + currPollID.ToString()); //added
}
return ret;
}
There are two new lines added. The first one gets the current poll ID, BEFORE the actual update is performed. This is the ID of the poll that is becoming âun-Currentâ. You need to get this value before the call to actually update the database, otherwise you will get the ID of the newly Current poll, which is not what you want. The second new line purges the poll that is becoming un-Current.
This ensures that only fresh data remains in the cache, and that poll DetailsView will display the right information.
Hope this helps some folks out.