Content By Query webpart

22 Jun

Recently I was fixing a bug which occurred at a custom webpart derived from the Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart.

The custom webpart has an EditorPart where the user is able to set some properties and after configuration the webpart shows an item from a list with custom formatting. Not too exciting.

The customer reported an error occurred every time the properties where set and he selected ‘Apply’ and ‘Save’ or ‘Publish’. After returning from the error page to the page with the webpart on it he pressed ‘Save’ or ‘Publish’ again and the page was saved or published successfully.

The first thing is to start analyzing the ULS log messages belonging to the correlation id which belongs to the exception. The first unexpected exception:

‘Creating object wrapper, expecting major version, but no major version given.  URL is /xxxx’

followed closely by the message

‘Trying to store a checked out item (/xxx.ASPX) in the object cache.  This may be because the checked out user is accessing the page, or it could be that the SharePoint system account has the item checked out.  To improve performance, you should set the portalsuperuseraccount property on the web application’

Three things to check:

  1. the checked out user is accessing the page – well yes, that will be me configuring the page
  2. the SharePoint system account has the item checked out – no
  3. set the portalsuperuseraccount property on the web application – I already did, so no

And a lot of ‘ConsoleUtilies.GetContextualControlMode had no currentPage so the current SPWebPartManager mode cannot be retrieved.’ messages.

The categories these messages came from where Publishing and Publishing Cache, so I checked some of the cache policies applied to the site. To be sure it didn’t had to do anything with the cache configured in the solution, I moved the webpart to a clean SharePoint installation, but the same exception did occur.

The next unexpected exception:

‘System.Web.HttpException: 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.’

Ah, the viewstate was changed during the postback. But I couldn’t find anything in the code which would be responsible for that, except…

The QueryOverride property was set in the EditorPart when configuring the webpart and this property wasn’t available in the .webpart file.

When the QueryOverride property is set SharePoint adds a new label to the toolpane with the message ‘Some properties in this Web Part are not available because they are configured to have fixed values’:

The message is fine, because that’s the purpose of the QueryOverride property, but the label changed the viewstate, because the QueryOverride wasn’t set at the initial loading state of the webpart, and occurred the exception.

To solve this issue the QueryOverride property has to be set before the first time the viewstate is loaded. Afterwards it can be changed to another value, which will happen because this webpart changes the QueryOverride when a user changes one of the properties of the webpart.

To set the QueryOverride property before the viewstate is loaded there are two option: set the property in the OnInit event or add the property to the .webpart definition file.

OnInit event

Only set a sort of dummy property value when the QueryOverride property is empty.

protected override void OnInit(EventArgs e)
{
  base.OnInit(e);

  string baseOverride = "<Where><Eq><FieldRef Name='ID'/><Value Type='Counter'>0</Value></Eq></Where>";
  if (this.QueryOverride.Equals(string.Empty))
  {
    this.QueryOverride = baseOverride;
  }
}

Webpart definition file

Add a dummy QueryOverride property to the xml file.

<property name="QueryOverride" type="string">&lt;Where&gt;&lt;Eq&gt;&lt;FieldRef Name='ID'/&gt;&lt;Value Type='Counter'&gt;0&lt;/Value&gt;&lt;/Eq&gt;&lt;/Where&gt;</property>

Summary

Sometimes the content query webpart is somewhat inconvenient and you’ll have to implement some fixes to get around it.

Of the two possible solutions provided for this inconvenience there is no ‘best one’, but I prefer using the OnInit method, because developers including myself, are most of the time investigating the code before the accompanying definition files.

Both solutions add the label

to the toolpane right away and the viewstate won’t change during a postback.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.