What does TaxonomyItem.NormalizeName() do?

So, the client side application I’ve been working on has to sync a LOT of terms to the term store, and I’ve mentioned how I had problems with Managed Metadata labels and the ampersand – and how I fixed them using TaxonomyItem.NormalizeName().

Well, that was fine, but my application was slow – so I started looking at what I could do to eliminate client side object model calls (CSOM). My suspicion was that, as the function was static, it wasn’t doing anything that I couldn’t do in my application, and save a round trip to the server.

So, I opened up reflected and decompiled Microsoft.SharePoint.Taxonomy.dll. Inside I found the code for the following:

Regex _trimSpacesRegex = new Regex(@"s+", RegexOptions.Compiled | RegexOptions.IgnoreCase);
//Normalize name as Taxonomy Service does
string name = _trimSpacesRegex.Replace(termName, " ").Replace('&', 'uff06').Replace('"', 'uff02').Trim();

That’s much, much faster than a round trip to the server, and I learnt that speechmarks are also converted from ASCII to Unicode too.

Advertisement
What does TaxonomyItem.NormalizeName() do?

Managed Metadata Labels and the Ampersand character

I am writing an application to import/generate a number of terms in a term set. I started to get some errors about my code trying to add terms that already exist – but it does check for the existence of terms with a given name.My Code and existence check

You can see that the string comparison for the name of the existing term and the term I want to get/create returns false, and that the terms seem to be different lengths. Well, I tried looking for blank spaces, non-printing characters, carriage returns, etc., and found nothing. Then I looked really closely at the ampersand characters shown in the debugger:

Strings in the Debugger

Yup, they’re different characters. You can see a slightly different shape to each of them – one is wider. Continue reading “Managed Metadata Labels and the Ampersand character”

Managed Metadata Labels and the Ampersand character

What happens with a large TaxonomyHiddenList?

SharePoint’s Taxonomy (or “Managed Metadata”) fields are a bit strange in how they work. In a lot of ways they’re actually like a lookup field, and part of this lookup field is that site collections that use them have a hidden list – called TaxonomyHiddenList – in the root of the site collection. You can find it at /lists/TaxonomyHiddenList/.

Hidden

Each term that is used in a Taxonomy field has it’s label (actually, labels) and other details kind of ‘cached’ in this list, and there is a timer job that will push changes to the terms out into these lists – and therefore to items that refer to the entries in the list. Continue reading “What happens with a large TaxonomyHiddenList?”

What happens with a large TaxonomyHiddenList?

Tabular Search Results with Column Filters

The customer I was with last week, like many others, wanted their search results to appear in a table form – like a List View, in fact.

List View Search Results

Now, I’ve written the XSL to do this for various solutions over the years, but they had found a CodePlex project for this – SharePoint 2010 Search Results in Tabular Format. This project has a feature I’d not managed to write, or had seen working before – column titles that were sortable and filterable:

Sorting and Filtering on Columns

That’s pretty neat. And it’s all XSL. You can, if you edit the XSL and the Columns you get back from search, show, sort, and filter other columns of data.

One observation I would make is that this XSL does not format Hit Highlighting – that is, matches aren’t shown as strong, and the summary doesn’t contain any ellipsises [ … ] characters. However, you could easily add these from the ‘standard’ XSL to get hit highlighting working again.

Tabular Search Results with Column Filters

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;
}
}
}
Setting the Title field for Content Types

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.

BeforeProperties and AfterProperties

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 “ContentIterator – Curious Behaviour, and Infinite looping”

ContentIterator – Curious Behaviour, and Infinite looping

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.

Delete Event Receiver from a Content Type with Code

Strange issue with Application Page and Two Button Presses

Okay, this one was weird. The symptom is this – I had a custom Application page that was being used as the New and Edit forms for a particular custom list in my solution. One of the customisations was that it had an ‘Address Search’ button that, when you pressed, searched for an address based on the first line of the address, or the postcode.

That’s fine, but here’s where things got weird.

  • If you were using the form as a New form, then search worked just fine the first time you clicked it.
  • If you were using the form as an Edit form, the the search button didn’t work the first time you use it – but did the second time you clicked on it.

Bizarre, and I had to fix it… Continue reading “Strange issue with Application Page and Two Button Presses”

Strange issue with Application Page and Two Button Presses