I recently created a custom web part in SharePoint that derived from the ContentByQueryWebPart class. In the OnLoad method I pulled some managed metadata values from the query string and used them to set the “QueryOverride” property on the web part. I tested my web part on a page, and at first glance everything appeared to be fine.
Then I tried to edit the web part and periodically got this error whenever I hit one of the buttons (OK, Cancel, or Apply) in the web part’s editing tool pane:
Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request. For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.
Huh? Where did this come from? I did a quick search on Bing and discovered the problem appeared to be a label that Microsoft dynamically adds to the tool pane when the QueryOverride property is set. The label basically warns the user that parts of the tool pane UI will be disabled because the query is being set in code. Apparently what happens is the tool pane initially loads without the label, then QueryOverride was set in OnLoad (after viewstate is initially loaded), and then the label is added. After the postback, ASP.NET is confused by the extra label that wasn’t there when viewstate was first loaded.
I found a few strange workarounds on the Internet (including “resetting” the QueryOverride property by setting it to an empty string after CreateChildControls() is called), but none of them worked.
In the end, I decided to try setting QueryOverride earlier in the page lifecycle before viewstate was loaded. That worked. Moving my code from OnLoad to OnInit solved the problem (no strange workarounds required).