1

I am working on an event receiver inside sharepoint server 2013. the event receiver will fire when a user added a new item inside a custom list. Now i am trying to do the following :-

1- get the current item title using properties.ListItem.Title;

2- search the term store based on the item title.

3- create a new wiki page, add for the wiki category column to assign it the term i retrieved on step-2.

now i have the following code:-

public override void ItemAdded(SPItemEventProperties properties)
 {
base.ItemAdded(properties);

    PublishingSite pSite = new PublishingSite(properties.Site);
    SPContentType ctype = pSite.ContentTypes["Enterprise Wiki Page"];
    PageLayoutCollection pageLayouts = pSite.GetPageLayouts(ctype, true);
    PageLayout pageLayout = pageLayouts["EnterpriseWiki.aspx"];
    PublishingWeb pWeb = PublishingWeb.GetPublishingWeb(properties.Web);
    PublishingPageCollection pPages = pWeb.GetPublishingPages();
    PublishingPage pPage = pPages.Add(newPageName+".aspx", pageLayout);
    newpage["Wiki_x0020_Page_x0020_Categories"] = properties.ListItem.Title.Trim();

now i was not expecting my above code to work, as i am trying to assign a string to a managed property column. so i got this error:-

The given guid does not exist in the term store

so can anyone advice how i can search the term store and get the related term which is equal to the properties.ListItem.Title and then assign the term to the newpage["Wiki_x0020_Page_x0020_Categories"] column ?

  • Take a look here: social.msdn.microsoft.com/Forums/en-US/… – Cecilia Feb 1 '17 at 17:00
  • Here Wiki_x0020_Page_x0020_Categories is taxonomy column and you want to set its value to properties.ListItem.Title. Correct ? Also, properties.ListItem.Title value (term) will be present in term store, is that correct ? – Gautam Sheth Feb 1 '17 at 17:38
  • @GautamSheth yes to both questions Wiki_x0020_Page_x0020_Categories is taxonomy and properties.ListItem.Title is presented in the term store – john Gu Feb 1 '17 at 18:21
1

Try either of the below 2 approaches, should work:

Approach 1:

SPList oList = oWebsiteRoot.Lists[listName];  //get the list name
TaxonomySession session = new TaxonomySession(properties.Site); //pass spsite object
TaxonomyField oField = oList.Fields["Wiki_x0020_Page_x0020_Categories"] as TaxonomyField; //pass internal name of column
TermSet oSet = session.DefaultSiteCollectionTermStore.GetTermSet(oField.TermSetId);
TermCollection oColl = oSet.Terms;
foreach (Term oTerm in termColl)
{
    if (oTerm.Name == properties.ListItem.Title)
    {
        TaxonomyField taxonomyField = oList.Fields["Wiki_x0020_Page_x0020_Categories"]as TaxonomyField;
        TaxonomyFieldValue taxonomyFieldValue = new TaxonomyFieldValue(taxonomyField);
        taxonomyFieldValue.TermGuid = oTerm.Id.ToString();
        taxonomyFieldValue.Label = oTerm.Name;

        newpage["Wiki_x0020_Page_x0020_Categories"] = taxonomyFieldValue;
        item.Update(); //splistitem update
        oList.Update(); //probably not necessary
        break;
    }
}

Approach 2: Traverse the term store

string listName = "CustomList";
string fieldName = "Wiki_x0020_Page_x0020_Categories";
SPList oList = oWebsiteRoot.Lists[listName];  //pass the splist 
TaxonomyField oField = (TaxonomyField)oList.Fields[fieldName];

// Get a TaxonomySession from the site
TaxonomySession session = new TaxonomySession(properties.Site);
TermStore termStore = null;
// Get a TermStore from the session
if (session.TermStores != null)
{
    termStore = session.TermStores[oField.SspId];
}

foreach(Group g in termStore.Groups)
{
    TermSet termSet = g.TermSets.FirstOrDefault(t => t.Id == oField.TermSetId);

    if (termSet != null)
    {
        Term term = termSet.Terms[properties.ListItem.Title]);      
        TaxonomyFieldValue taxonomyFieldValue = new TaxonomyFieldValue(oField);
        taxonomyFieldValue.TermGuid = term.Id.ToString();
        taxonomyFieldValue.Label = term.Name;
        newpage["Wiki_x0020_Page_x0020_Categories"] = taxonomyFieldValue;
        item.Update();  //splistitem update
        oList.Update();  //probably not necessary
        break;
    }
}
  • your second appraoch looks good, although in my case i am using the server-side object and not the client side object,, but will try to convert it into server-side and test the result.. – john Gu Feb 6 '17 at 1:30
  • This is server side code only. – Gautam Sheth Feb 6 '17 at 2:39
1

EDIT: This is an answer for using CSOM, not SSOM, which is what the code sample in the question uses.

Dealing with taxonomy terms is much more complicated than it seems on the surface. To get a term efficiently so you don't have to iterate over the whole taxonomy store, you need to know the term group name and the term set name. Here is a handy helper function, which I use to get a term by title. Provide properties.ListItem.Title for the termName argument.

public static Term GetTerm(ClientRuntimeContext ctx, string groupName, string termSetName, string termName)
    {
        TaxonomySession session = TaxonomySession.GetTaxonomySession(ctx);
        TermStore store = session.GetDefaultSiteCollectionTermStore();
        TermGroup group = store.Groups.GetByName(groupName);
        TermSet termSet = group.TermSets.GetByName(termSetName);
        TermCollection terms = termSet.GetAllTerms();
        ctx.Load(terms, a => a.Where(t => t.Name == termName));
        ctx.ExecuteQuery();
        Term term = terms.FirstOrDefault();
        return term;
    }

If the above function returns null, than it cannot find a term by that name in that term set. Once you get the term, setting the value of the Wiki_x0020_Page_x0020_Categories field using that term can be tricky. Interestingly, there are many ways to set a TaxonomyField value, but I demonstrate one below that I have used previously.

public void SetTaxonomyFieldValue(Field taxonomyField, Term term, ListItem item)
    {
        //make sure the TypeAsString property is loaded
        if (taxonomyField.IsObjectPropertyInstantiated("TypeAsString") == false)
        {
            taxonomyField.Context.Load(taxonomyField, f => f.TypeAsString);
            taxonomyField.Context.ExecuteQuery();
        }
        //if a multi-select managed metadata field
        if (taxonomyField.TypeAsString == "TaxonomyFieldTypeMulti")
        {
            //Cast Field to TaxonomyField
            TaxonomyField taxField = (TaxonomyField)taxonomyField;
            //create a value string for the field value. You cannot use TaxonomyField.SetFieldValueByTerm since Term.Context != Field.Context
            string strValue = string.Format("-1;#{0}|{1}",term.Name,term.Id);
            TaxonomyFieldValueCollection taxonomyFieldValueCollection = new TaxonomyFieldValueCollection(taxonomyField.Context, strValue, taxonomyField);
            taxField.SetFieldValueByValueCollection(item, taxonomyFieldValueCollection);
        }
    }
  • thanks a lot for your detailed reply,, but in my case the TermStore.Groups do not have any method name .GetByName?? i will only get these 3 methods for Get; GetType, GetHashcode &GetEnumerator?? can you adivce on this ? here is the error i will get Microsoft.SharePoint.Taxonomy.GroupCollection' does not contain a definition for 'GetByName' and no extension method 'GetByName' accepting a first argument of type 'Microsoft.SharePoint.Taxonomy.GroupCollection' could be found (are you missing a using directive or an assembly reference? – john Gu Feb 3 '17 at 16:10
  • 1
    Hmm which version of SharePoint are you using and which version of CSOM assemblies do you have? – Kevin Stone Feb 3 '17 at 22:16
  • i am using the server-side object inside my event receiver (as shown in my code) and not the client side object. – john Gu Feb 6 '17 at 1:22
  • My mistake - the code is pretty similar and I didn't notice. – Kevin Stone Feb 6 '17 at 15:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.