A hybrid SharePoint environment means a combination of SharePoint on-premise farm and Office 365 (O365) SharePoint online (SPO) farm to leverage both platforms advantages.
In this post, I will demonstrate a console client solution that reads and writes taxonomy items from/to SPO platform and share some tips relevant to taxonomy in your farm or hybrid farm design. The solution works for on-premise as well (that would be different site URL and credentials off course)
I am going to extend the sample code from an msdn article –Managed metadata and navigation in SharePoint 2013 – I wanted to confirm that it applies to SPO context as well.
Requirements:
SPO farm (at least term store admin account provisioned) Visual Studio 2012/2013 (I am using v2013) with Office Developer Tools
Ok, lets start the demonstration, will ignore minor steps.
- By using VS create a console project Add assembly references of those to the project:
Microsoft.SharePoint.Client
Micrososft.SharePoint.Client.Runtime
Microsoft.SharePoint.Client.Taxonomy
Copy the exactly same code from msdn mentioned above.
In order to make that code working, you need to supply the correct site URL and credentials as demonstrated below and adjust the copied methods accordingly. Note that 3 keys taken from config file:
- siteUrl: the URL for SPO site. It follows “https://<mytenantname>.sharepoint.com/" structure where <…> implies your tenant name for O365 account pwd: the tenant password tenant: the tenant username in the format of “<myusername>@<mytenantname>.onmicrosoft.com”
And, action
1: static string _siteUrl;
2: static SharePointOnlineCredentials _credentials;
3:
4: public static void Main(string[] args)
5: {
6: try
7: {
8: _siteUrl = System.Configuration.ConfigurationManager.AppSettings["siteUrl"];
9:
10: var password = new SecureString();
11: System.Configuration.ConfigurationManager.AppSettings["pwd"].ToList().ForEach(n => password.AppendChar(n));
12: _credentials = new SharePointOnlineCredentials(System.Configuration.ConfigurationManager.AppSettings["tenant"], password);
13:
14: CreateColorsTermSet();
15: DumpTaxonomyItems();
16: }
17: catch (Exception ex)
18: {
19: var msg = ex.Message;
20: //TODO:log this
21: }
22: }
1: private static void CreateColorsTermSet()
2: {
3: ClientContext clientContext = new ClientContext(_siteUrl);
4: clientContext.Credentials = _credentials;
5:
6: TaxonomySession taxonomySession = TaxonomySession.GetTaxonomySession(clientContext);
7: clientContext.Load(taxonomySession,
8: ts => ts.TermStores.Include(
9: store => store.Name,
10: store => store.Groups.Include(
11: group => group.Name
12: )
13: )
14: );
15: clientContext.ExecuteQuery();
16:
17: if (taxonomySession != null)
18: {
19: TermStore termStore = taxonomySession.GetDefaultSiteCollectionTermStore();
20: if (termStore != null)
21: {
22: //
23: // Create group, termset, and terms.
24: //
25: TermGroup myGroup = termStore.CreateGroup("MyGroup", Guid.NewGuid());
26: TermSet myTermSet = myGroup.CreateTermSet("Color", Guid.NewGuid(), 1033);
27: myTermSet.CreateTerm("Red", 1033, Guid.NewGuid());
28: myTermSet.CreateTerm("Orange", 1033, Guid.NewGuid());
29: myTermSet.CreateTerm("Yellow", 1033, Guid.NewGuid());
30: myTermSet.CreateTerm("Green", 1033, Guid.NewGuid());
31: myTermSet.CreateTerm("Blue", 1033, Guid.NewGuid());
32: myTermSet.CreateTerm("Purple", 1033, Guid.NewGuid());
33:
34: clientContext.ExecuteQuery();
35: }
36: }
37: }
38:
39: private static void DumpTaxonomyItems()
40: {
41: ClientContext clientContext = new ClientContext(_siteUrl);
42: clientContext.Credentials = _credentials;
43:
44: //
45: // Load up the taxonomy item names.
46: //
47: TaxonomySession taxonomySession = TaxonomySession.GetTaxonomySession(clientContext);
48: TermStore termStore = taxonomySession.GetDefaultSiteCollectionTermStore();
49: clientContext.Load(termStore,
50: store => store.Name,
51: store => store.Groups.Include(
52: group => group.Name,
53: group => group.TermSets.Include(
54: termSet => termSet.Name,
55: termSet => termSet.Terms.Include(
56: term => term.Name)
57: )
58: )
59: );
60: clientContext.ExecuteQuery();
61:
62:
63: //
64: //Writes the taxonomy item names.
65: //
66: if (taxonomySession != null)
67: {
68: if (termStore != null)
69: {
70: foreach (TermGroup group in termStore.Groups)
71: {
72: Console.WriteLine("Group " + group.Name);
73:
74: foreach (TermSet termSet in group.TermSets)
75: {
76: Console.WriteLine("TermSet " + termSet.Name);
77:
78: foreach (Term term in termSet.Terms)
79: {
80: //Writes root-level terms only.
81: Console.WriteLine("Term " + term.Name);
82: }
83: }
84: }
85: }
86: }
87:
88: Console.ReadLine();
89:
90: }
F5 and voila!
Please note that:
-
The username used for R/W (can be any CRUDQ) operations on taxonomy engine must be a term store administrator.
The group name must be unique
This demonstration uses SCOM API, yet with JSOM API, it is just fine.
Taxonomy defined in SPO and on-premise farms are not integrated (by design). This can be a problem if both farms have content indexed. Perhaps, this demonstration should give you the idea how to come up with a global taxonomy (for hybrid scenarios). Remember that taxonomy ultimately defines the information architecture.
Each taxonomy entry (group, term set, or terms) defined with unique Ids – Guid – by which the specific item can be queried (CRUDQ).