Category Archives: SharePoint-Development

Bug with Internet Explorer and grid RowEditing-plugin when using scoped-theme

I came across this rare bug in the current development of a project. It makes heavy use of the RowEditing plugin of Extjs‘ grid. Because the Extjs environment is used within SharePoint 2010 I have to use the scoped theme to avoid “damage” to the SharePoint UI.

After inserting a record into the grid via RowEditing and pressing cancel the RowEditings’ editor window is not shown. You guess it right: only when using Internet Explorer (7, 8, 9). After testing it showed that the css itself is not the reason. So debugging the Extjs-source where the setting scopeResetCSS is evaluated…

The final result is a workaround applied via Ext.override to solve the “problem”.

if(Ext.isIE) {
  Ext.AbstractComponent.override({
    onRender: function(container, position) {
      var me = this,
        el = me.el,
        styles = me.initStyles(),
        renderTpl, renderData, i;
 
      position = me.getInsertPosition(position);
 
      if(!el) {
        if(position) {
          el = Ext.DomHelper.insertBefore(position, me.getElConfig(), true);
        }
        else {
          el = Ext.DomHelper.append(container, me.getElConfig(), true);
        }
      }
      else if(me.allowDomMove !== false) {
        if(position) {
          container.dom.insertBefore(el.dom, position);
        } else {
          container.dom.appendChild(el.dom);
        }
      }
 
      if(Ext.scopeResetCSS && !me.ownerCt) {
 
        if(el.dom == Ext.getBody().dom) {
          el.parent().addCls(Ext.baseCSSPrefix + 'reset');
        }
        else {
          if(me.$className != 'Ext.grid.RowEditor') {
            me.resetEl = el.wrap({
              cls: Ext.baseCSSPrefix + 'reset'
            });
          }
        }
      }
 
      me.setUI(me.ui);
 
      el.addCls(me.initCls());
      el.setStyle(styles);
      me.el = el;
 
      me.initFrame();
 
      renderTpl = me.initRenderTpl();
      if(renderTpl) {
        renderData = me.initRenderData();
        renderTpl.append(me.getTargetEl(), renderData);
      }
 
      me.applyRenderSelectors();
 
      me.rendered = true;
    }
  });
}

The woraround itself is only this:

if(me.$className != 'Ext.grid.RowEditor') {
  me.resetEl = el.wrap({
    cls: Ext.baseCSSPrefix + 'reset'
  });
}

BTW: I “love” IE!

Enable-SPFeature does not trigger the feature receiver

Today I encountered the same problem as stated in a blog post by Christopher Maish. When activating the feature via powershell the associated feature receiver was not called.

Trying the suggested solution in the blog post drove me to the cause of this problem. When using stsadm I got an “access denied” error.
I did run my script via Powershell ISE within Windows Server 2008.

So the real problem is caused, again, by UAC (User Account Control). When starting the Powershell ISE with “Run as administrator” and executing the script the feature receiver is now called as expected. Even when using Enable-SPFeature!

Using powershell to quickly debug SPSiteDataQuery

Writing CAML-Queries is still no fun. Even with SharePoint 2010… So you often need to test your queries before they actually work.

In case you quickly want to test if your SPSiteDataQuery is correct you can use powershell to “debug” it. Just create an instance of the site-collection and target the root-web with your query-instance.

$site = Get-SPSite -Identity http://my-site-collection
 
$q = New-Object -typeName Microsoft.SharePoint.SPSiteDataQuery
$q.Query = "<Where><And><Eq><FieldRef Name='ContentType'/><Value Type='Text'>MyCT</Value></Eq><BeginsWith><FieldRef Name='Url'/><Value Type='URL'>/path</Value></BeginsWith></And></Where>"
$q.ViewFields = "<FieldRef Name='ID'/><FieldRef Name='ContentType'/>"
$q.Webs = "<Webs Scope='SiteCollection' />"
 
$site.RootWeb.GetSiteData($q)

This is way faster than doing it in VS…

Using a C# preprocessor directive for testing custom timer-jobs

If your are writing custom timer-jobs for your SharePoint solution it will happen that you write jobs which are only executed once a day or even less often. As a developer you cannot wait that long…

You could of course comment in and out (via ctrl + k, ctrl + c / ctrl + k, ctrl + u) the SPSchedule used by the timer-job during debug-mode. But this is error-prone.

When using a C# preprocessor directive you cannot forget to switch back to the “production schedule” as this is done automatically (and even with syntax-highlighting depending on the active configuration!) when selecting the “release build”.


#if (DEBUG)
var schedule = new SPMinuteSchedule();
schedule.BeginSecond = 1;
schedule.EndSecond = 59;
schedule.Interval = 5;
#else
var schedule = new SPDailySchedule();
schedule.BeginHour = 7;
schedule.EndHour = 7;
schedule.BeginMinute = 1;
schedule.EndMinute = 59;
#endif

This code tells the compiler to use the SPMinuteSchedule when compiling the “debug build” and to use the SPDailySchedule when compiling in “release build”. All automatically!

Updating existing lookup fields in SharePoint

Creating lookup-fields only via XML-Definition is not possible. You need the ID of the Web hosting the list and the ID of the list hosting the data the lookup field is connected to. This information can only be retrieved when both entities are created…

Object model?!

When looking into the SPFieldLookup-class you find the properties LookupField, LookupList and LookupWebId. LookupWebId and LookupField can easily be set via the object model. The documentation says that LookupList is read and writeable which is not true. Setting LookupList throws an exception stating out “Cannot change the lookup list of the lookup field.”.

SchemaXml and Regex to the rescue

The SchemaXml-property of a SPField can be used to manipulate the LookupList. One stumbling block is that you do not know the Guid of the LookupList currently stored in the schema. Even if you define a Guid inside your xml-field-definition SharePoint puts in an other Guid. Here a simple regular expression comes to help.

The code for connecting a site-column with a list somewhere in some web:

// Declarations (myWeb is the context given by a feature receiver scoped "web")
var rx = new Regex("List=\"([^\"]*)\"", RegexOptions.IgnoreCase | RegexOptions.ECMAScript);
var root = myWeb.Site.RootWeb;
 
// myListInstance is an instance of a SPList existing somewhere
var lookupField = (SPFieldLookup)root.Fields["MyLookupField"];
var xml = lookupField.SchemaXml;
xml = rx.Replace(xml, String.Format("List=\"{0}\"", myListInstance.ID.ToString("B")));
lookupField.SchemaXml = xml;
// Do not call update here!
// Quote from MSDN "Do not call the Update method when using the SchemaXml  property to modify a field."
 
// Fetch the field again and apply the web-id
var lookupFieldReFetch = (SPFieldLookup)root.Fields["MyLookupField"];
lookupFieldReFetch.LookupWebId = myWeb.ID;
lookupFieldReFetch.LookupField = "Title";
lookupFieldReFetch.Update(true);

This problem still persists in the beta of SharePoint 2010. I hope this will get fixed in the RTM. Creating a lookup-field-connection is far more easy by the way …