Setting the Title field for Content Types

This is one I’ve been meaning to blog about for a while. I was using a Content Type where I was trying to set the display name of ‘Title’ field. I was happy to have a Title column, but I wanted it to have a different name.

I tried doing this declaratively:

<FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" DisplayName="Request" Required="FALSE" />

However, I found this didn’t work in SP2010 – the field still appeared as ‘Title’. This was frustrating.

Instead, I had to set the Title’s display name in code:

foreach (SPFieldLink fldLnk in contentType.FieldLinks)
{
if (fldLnk.Id == SPBuiltInFieldId.Title)
{
fldLnk.DisplayName = "Request";
}
}
contentType.Update(false);

This was a bit strange – other fields can have a DisplayName set in CAML quite happily. This seems to just be a feature of the Title column.

EDIT: I also had to use a similar approach on setting the Title column for a content type used on a list – but using:

private void SetTitleField(SPWeb web, string listname, string contentTypeName, string newTitleName) 
{
SPList list = web.Lists[listname];
SPContentType ct = list.ContentTypes[contentTypeName];

foreach (SPFieldLink fldLnk in ct.FieldLinks)
{
//Necessary to set title field - when using content types, this seems to set it to "Title" irrespective of what is set in the Content type or list's XML.
if (fldLnk.Id == SPBuiltInFieldId.Title)
{
	fldLnk.DisplayName = newTitleName;
	ct.Update(false);
	break;
}
}
foreach (SPField fld in list.Fields)
{
if (fld.Id == SPBuiltInFieldId.Title)
{
	fld.Title = newTitleName;
	fld.Update();
	break;
}
}     
}

Refinements panel and Custom Search Box web parts

So I’m doing some work for a customer where they want a custom Search Box web part. Essentially, they want to be able to search by particular managed properties, which is a pretty common scenario:

CaptureNaturally, I added this to my search results page, and removed the existing Search Box web part.

During test, the customer noticed that the ‘Show More’ links on the refinement panel had stopped working:

Capture2Interesting – although showing some different metadata properties, this was all pretty standard stuff. A bit of a check on Google found this interesting post by Chris Coulson. The short if it is that the Refinements panel uses JavaScript that is loaded by the Search Box web part – so you have to have a Search Box web part on the results page, even if it is hidden. Add that and the Refinement panel works again.

You can hide the web part via the web part properties > Layout > Hidden.

The Importance of knowing Regular Expressions

It’s something that always mystifies me, it does seem that a lot of developers don’t know regular expression syntax very well. This came up when I was on some SharePoint 2013 training just before Christmas.

SharePoint 2013 introduces something called “Routing Rules”. These are rules that allow you to direct traffic to different front-end servers (or pools of servers), allowing you to isolate traffic, route to better health servers, etc.. Spence Harbar has a very good article about it.

Anyway, one some of the criteria that you can match rules on are Regular Expressions. However, SharePoint does warn you that Regex routing rules are slower – this is unsurprising. But how much slower than, say, a ‘Starts with’ or ‘Ends with’ rule? And on the Ignite training I did wonder about the efficiency of their example… Continue reading

Annoying Exporting a list to Excel

SharePoint lists have the ability to export their contents to an Excel Workbook.

This is quite cute – it gives the users a way to get the data out into something they’re familiar with, can manipulate and can print. However, I was having an issue. Using a list based on a Custom List (above), one of my columns (Enquiry) wasn’t exported:

I wondered at first if this was because of it’s column type (Hyperlink), or because I’d created the column programmatically. Then, on a hunch really, I tried changing the column order. I added another column before it in the list view. I used the ID column, but any should work. When I exported the list – all the columns I wanted came through (but the ID column didn’t).

What I think is going on here is that if you used the same export on a document library then typically – though not always – the first column is an icon for the type of file it is. My suspicion is that some muppet, when writing the export to excel, realised that they’d have these icons, and decided to avoid them by excluding the first column. This is unfortunate for two reasons:

  • Not all lists have icons – witness my Custom List
  • Not all document libraries have the file icon as the first column.

For now the resolution would be to have another column as the first on your list.

BeforeProperties and AfterProperties

I am sick of having to hunt down the link to Synergy’s post on the BeforeProperties and AfterProperties available in different events on SPListItems. For my reference, here it is:

List:

List BeforeProperties AfterProperties properties.ListItem
ItemAdding No value New value Null
ItemAdded No value New value New value
ItemUpdating No value Changed value Original value
ItemUpdated No value Changed value Changed value
ItemDeleting No value No value Original value
ItemDeleted No value No value Null

Document Library:

Library BeforeProperties AfterProperties properties.ListItem
ItemAdding No value No value Null
ItemAdded No value No value New value
ItemUpdating Original value Changed value Original value
ItemUpdated Original value Changed value Changed value
ItemDeleting No value No value Original value
ItemDeleted No value No value Null

Note: Allegedly, this does change if the event receiver is synchronous - the before properties are available. I’ve not checked this out yet.

Obviously, for SharePoint 2007 systems that doesn’t apply – as ‘*ed’ event receivers are always asynchronous.

ContentIterator – Curious Behaviour, and Infinite looping

I like the ContentIterator control – it’s a nice way of being able to process a lot of items in SharePoint. However, sometimes it’s behaviour is … strange.

I had been using it to loop over some (but not all) the items in a list. Some changes meant that I was now going to loop over all the items. I had a list with 500 items that I was testing with. My code was:

ContentIterator ci = new ContentIterator("example");
SPQuery qry = new SPQuery();
qry.Query = ContentIterator.ItemEnumerationOrderByNVPField;
ci.ProcessListItems(list,qry, ProcessItem, ProcessItemError);

This would process the first 200 items, over and over. It never reached an end. Hmm. Continue reading

Delete Event Receiver from a Content Type with Code

SharePoint allows you to attach event receivers to content types. That’s pretty handy. Unfortunately, deleting event receivers from those content types is much more hard. Perhaps this is why the Document ID feature fails to remove the content types that it adds. However, here is one possible approach.

SPContentType ctype = site.RootWeb.ContentTypes[SPBuiltInContentTypeId.Document];
if (ctype != null)
{
 if (ctype.EventReceivers != null)
 {
   bool bContinueDelete = true;
   while (bContinueDelete)
   {
     if (ctype.EventReceivers.Count < 1)
     {
       bContinueDelete = false;
     }
     else
     {
     bool bFoundOne = false;
     foreach (SPEventReceiverDefinition d in ctype.EventReceivers)
     {
         //Could match on the Type of the event receiver, but for this example, let's use name
         if (d.Name.Contains("Document ID"))
         {
           d.Delete();
           ctype.Update(true, false);
           bFoundOne = true;
           break;
         }
     }
     if (!bFoundOne)
     {
       bContinueDelete = false;
     }
   }
 }
}

More on why this is important in a later post.

Slow Site Creation in SharePoint 2010

I have a development machine that I was creating a number of sites within. I wanted to create about 10,000 sites or so (and have done more than that in testing before without a problem). When I started the process that was creating these running on my machine it was taking about 20 seconds per site. After a mere 2000 sites, it was then talking 30 minutes per site. Something isn’t right.

I did a bit of digging and found that others have had the same problem – but no solution.

I then spoke to one of our administrators, and he suggest clearing out the ‘event cache’ table. I’d never heard of that (and I’ve no idea how he found out about it), but his advice was:

Minimise the amount of rows in the EventCache SQL table:

  • set ChangeLogRetentionPeriod to 1 day (1.00:00:00) on web application
  • set EventLogRetentionPeriod to 1 day (1.00:00:00) on web application
  • set ‘Change Log’ timer job to run daily (default is weekly)

Okay, so I did this using STSADM:

stsadm -o setproperty -pn change-log-retention-period -pv 1
stsadm -o setproperty -pn event-log-retention-period -pv 1

…and I then changed the Change Log timer job’ schedule in central admin, and set it running right away.

The timer job took about 8 minutes to run. That was a surprisingly long time.

When I then tried creating a site, it took 7 minutes. Clearly, this is still an unwell system, but that’s a lot better than 30 minutes. I’ll update if I find more.