Second Life of a Hungarian SharePoint Geek

December 23, 2010

How to create WssId for terms that are not yet referenced from the site

Filed under: Reflection, SP 2010, Taxonomies — Tags: , , — Peter Holpar @ 00:45

About a year ago I wrote about TaxonomyFieldValue and its WssId property. In a recent comment I got the question how to get the WssId for terms that are not referenced by the list items on the site.

I tried to answer the question there, but to provide a full example, I decided to post a code sample as well.

As described in the original post, the lookup item for the term and the corresponding WssId is created on the site through the private AddTaxonomyGuidToWss method.

One could call that method directly using reflection to generate the WssId for a term not yet in use on the site.

The following method – having the same name and signature as the original one – illustrates this call:

  1. private int AddTaxonomyGuidToWss(SPSite site, Term term, bool isKeywordField)
  2. {
  3.     int result = -1;
  4.  
  5.     Type taxonomyFieldType = typeof(TaxonomyField);
  6.  
  7.     MethodInfo mi_AddTaxonomyGuidToWss = taxonomyFieldType.GetMethod("AddTaxonomyGuidToWss",
  8.             BindingFlags.NonPublic | BindingFlags.Static, null,
  9.             new Type[3] { typeof(SPSite), typeof(Term), typeof(bool) },
  10.             null
  11.             );
  12.     if (mi_AddTaxonomyGuidToWss != null)
  13.     {
  14.         result = (int)mi_AddTaxonomyGuidToWss.Invoke(null, new object[3] { site, term, isKeywordField });
  15.     }
  16.  
  17.     return result;
  18. }

The original AddTaxonomyGuidToWss method returns the WssId for the lookup item created for the term on the site or –1 if the creation is failed for some reason. Our wrapper method also returns –1 as the default value.

Let’s see a sample for its usage:

  1. private void CreateTermWssIdTest(SPSite site)
  2. {
  3.     TaxonomySession session = new TaxonomySession(site);
  4.     TermStore termStore = session.TermStores["Managed Metadata Service"];
  5.     Group group = termStore.Groups["Test group"];
  6.     TermSet termSet = group.TermSets["Colors"];
  7.     Term term = termSet.Terms["Blue"];
  8.  
  9.     Console.WriteLine("Before creating local lookup item for term '{0}'", term.Name);
  10.     DisplayTermWssIdInfo(site, term);
  11.  
  12.     AddTaxonomyGuidToWss(site, term, false);
  13.  
  14.     Console.WriteLine("After creating local lookup item for term '{0}'", term.Name);
  15.     DisplayTermWssIdInfo(site, term);
  16. }
  17.  
  18. private void DisplayTermWssIdInfo(SPSite site, Term term)
  19. {
  20.     int[] wssIds = TaxonomyField.GetWssIdsOfTerm(site, term.TermStore.Id, term.TermSet.Id, term.Id, false, 1);
  21.  
  22.     Console.WriteLine("Lookup for term '{0}' using GetWssIdsOfTerm. WssId={1}", term.Name, wssIds.Length > 0 ? wssIds[0].ToString() : "Not found!");
  23.     Console.WriteLine("Lookup for term '{0}' using GetWssIdByTermId. WssId={1}", term.Name, GetWssIdByTermId(site.RootWeb, term.Id));
  24. }

First we check for the WssId of a term called “Blue” (assumed not in use on the site), then create the WssId and then try to display again the value of the WssId. For the definition of the GetWssIdByTermId method see the original post.

On a test run we should see something similar:

Before creating local lookup item for term ‘Blue’
Lookup for term ‘Blue’ using GetWssIdsOfTerm. WssId=Not found!
Lookup for term ‘Blue’ using GetWssIdByTermId. WssId=-1
After creating local lookup item for term ‘Blue’
Lookup for term ‘Blue’ using GetWssIdsOfTerm. WssId=1
Lookup for term ‘Blue’ using GetWssIdByTermId. WssId=1

Before creating the local lookup item, the static GetWssIdsOfTerm method of the TaxonomyField class returns an empty array, that is reported as Not found! by the DisplayTermWssIdInfo method. Our helper method GetWssIdByTermId returns the default –1 value.

As I’ve tested the code on a site just created for this test, this is the first lookup item in the hidden lookup list in the site root web. That is why the term added is reported as having value 1 in the WssId.

I hope this simple example helps to better understand the concept of WssId.

8 Comments »

  1. Hi Peter,

    Thank you for this excellent post how populate taxonomy fields with TaxonomyFieldValue \ TaxonomyFieldValueCollection in SharePoint 2010.
    This post saved me hours of developing time.

    ZKovacs

    Comment by Kovacs Zoltan — March 24, 2011 @ 08:26

  2. Thanks a lot. Your blog saved me a lot of time.

    Comment by ramesh — April 19, 2011 @ 15:09

  3. That saved my day 🙂

    Thank you so much!

    Comment by Firoz Ozman — August 9, 2011 @ 17:59

  4. Is there any translation of that code (esp. the method AddTaxonomyGuidToWss) to PowerShell available?

    Comment by PowerShell Geek — December 8, 2011 @ 16:08

    • I have not translated it to PS. If you would do that, please, share the result.

      Comment by Peter Holpar — December 8, 2011 @ 21:47

  5. Just a small suggestion that may help–rather than using reflection to call a private method, you can just create a TaxonomyFieldValue object and then retrieve the ValidatedString property. This property internally attempts to retrieve the WssId, and if it does not exist, will call the AddTaxonomyGuidToWss method.

    Comment by Larkin Young — April 12, 2012 @ 08:28

  6. You can also trigger the private method by getting the ValidatedString property of the TaxonomyFieldValue class.

    We use a function similar to the following:

    static int GetWssIdFromTermId(SPWeb web, Guid fieldId, Guid termId)
    {
    var field = web.AvailableFields[fieldId];
    TaxonomyFieldValue value = new TaxonomyFieldValue(field);
    value.TermGuid = termId.ToString();
    var dummy = value.ValidatedString;
    if (dummy != null)
    {
    return value.WssId;
    }
    return -1;
    }

    Note that the value of WssId is not set until after you access the ValidatedString property. Getting the value of the property has the side effect of populating the TaxonomyHiddenList if necessary.

    For the PowerShell version:

    function GetWssIdFromTermId ($web, $fieldId, $termId) {
    $field = $web.AvailableFields[$fieldId]
    $value = New-Object Microsoft.SharePoint.Taxonomy.TaxonomyFieldValue $field
    $value.TermGuid = $termId
    #Write-Host “DEBUG: Before $($value.WssId)”
    $dummy = $value.ValidatedString
    #Write-Host “DEBUG: After $($value.WssId)”
    return $value.WssId
    }

    Uncomment the DEBUG lines to see how WssId is populated by the call to the ValidateString property.

    Comment by Sly Gryphon — May 25, 2012 @ 02:33

  7. What if it’s metadata field accepting multiple values? Accessing the ValidatedString does not produce the same result.

    Comment by Half Abude — August 6, 2012 @ 13:51


RSS feed for comments on this post. TrackBack URI

Leave a comment

Create a free website or blog at WordPress.com.