Unfortunately, it seems that using this field type using a web service call is extremely complicated, and hardly seems to be documented at all (this is so typical of Sharepoint stuff...). Microsoft have given us a new web service class ("taxonomyclientservice") but there hardly any documentation on it all (http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.taxonomy.webservices.taxonomyclientservice.aspx).
Here is an example that I have managed to get working (after MUCH trial and error) that will hopefully help you to do the following:
- opens a list using the Lists web service,
- iterates through the fields in the default content type for the list (you can remove this bit and just iterate through the fields in the list if you like),
- if it finds a "TaxonomyFieldType" field, it then gets the "Shared Service ID" (GUID of managed meta-data service) and Term Set ID (GUID of term set defined on this field) required to run the Taxonomy web service call
- sets up the CAML to run the Taxonomy web service call,
- retrieves the taxonomy data for that field in XML.
Note that all my web service proxies are called "ListService" and "Taxonomys".
//get list data from webservice ListService.Lists listService = new ListService.Lists(); // Use your own list name XmlNode list = listService.GetList("My List Name"); // Let's have a look at it System.Diagnostics.Debug.Print(list.OuterXml); // Get the content types for this list //Get our defined content type (see previous post on how to do this - you need your own values here!) string contentTypeGuid = GetListContentTypeGuid("My List Name", "{GUID}", "My Content Type"); // Now get content type definition XmlNode contentType = m_listService.GetListContentType(mylistinfo.m_listName, contentTypeGuid); //Get the fields from the content type XmlNodeList nodes = RunXPathQuery(contentType, "//sp:Field"); // Loop through the fields in the content type foreach (XmlNode node in nodes) { // This stuff just sets up some variables based on the content type and skips over hidden fields string Name = node.Attributes["Name"].Value; if (Name == "ContentType") continue; string ID = node.Attributes["ID"].Value; if (string.IsNullOrEmpty(ID) || string.IsNullOrEmpty(Name)) continue; bool hidden = false; bool ReadOnly = false; try { hidden = Convert.ToBoolean(node.Attributes["Hidden"].Value); } catch { } try { ReadOnly = Convert.ToBoolean(node.Attributes["ReadOnly"].Value); } catch { } if (hidden || ReadOnly) continue; string ShowInFileDlg = ""; try { ShowInFileDlg = node.Attributes["ShowInFileDlg"].Value; } catch { } if (ShowInFileDlg == "FALSE") continue; string StaticName = node.Attributes["StaticName"].Value; string DisplayName = node.Attributes["DisplayName"].Value; // Now we can check the "Type" attribute string FieldType = node.Attributes["Type"].Value; if (FieldType == "TaxonomyFieldType") { // WE HAVE A TAXONOMY FIELD!!! // Lets get the shared service ID and the termset ID from teh List schema string sharedServiceIds = ""; string termSetId = ""; // jump a few nodes to get the correct bit of the schema (included for clarity) XmlNode childNode = node.ChildNodes[1]; XmlNode termNodes = childNode.ChildNodes[0]; //Loop through these nodes until we find the information we need foreach (XmlNode term in termNodes.ChildNodes) { System.Diagnostics.Debug.Print("term = " + term.ChildNodes[0].InnerText.ToString()); if (term.ChildNodes.Count > 1) { System.Diagnostics.Debug.Print("value = " + term.ChildNodes[1].InnerText.ToString()); if (term.ChildNodes[0].InnerText.ToString() == "SspId") { // Get shared services ID from list sharedServiceIds = term.ChildNodes[1].InnerText.ToString(); } if (term.ChildNodes[0].InnerText.ToString() == "TermSetId") { // Get Term Set ID from list termSetId = term.ChildNodes[1].InnerText.ToString(); } } } int lcid = System.Globalization.CultureInfo.CurrentUICulture.LCID; string serverTermSetTimeStampXml = ""; string termStoreIds = "<termStoreIds><termStoreId>" + sharedServiceIds + "</termStoreId></termStoreIds>"; string termSetIds = "<termSetIds><termSetId>" + termSetId + "</termSetId></termSetIds>"; //Always set timestamp to this string oldtimestamp = "<timeStamps><timeStamp>633992461437070000</timeStamp></timeStamps>"; //Always set version to 1 string clientVersion = "<versions><version>1</version></versions>"; string timeStamp = ""; // Taxonomy web service!! Taxonomys.Taxonomywebservice taxonomy = new Taxonomys.Taxonomywebservice(); taxonomy.Credentials = System.Net.CredentialCache.DefaultCredentials; string resultXML = taxonomy.GetTermSets(termStoreIds, termSetIds, lcid, oldtimestamp, clientVersion, out timeStamp); //Loop through the XML string termValue = "MHA"; string termGUID = ""; string parentID = ""; XmlDocument termSetXML = new XmlDocument(); termSetXML.LoadXml(resultXML); XmlNodeList terms = termSetXML.GetElementsByTagName("T"); foreach (XmlNode term in terms) { string termName = term.FirstChild.FirstChild.Attributes["a32"].Value; termGUID = term.Attributes["a9"].Value; try { parentID = term.Attributes["a25"].Value; } catch (Exception) { parentID = ""; } System.Diagnostics.Debug.Print("termName = " + termName + ", termGUID = " + termGUID + ", parentID = " + parentID); } } }
If you would like to know how to analyse the attribute codes returned in the XML, then take a look at this blog entry: http://blogs.solidq.com/sharepoint/Post.aspx?ID=37&title=SharePoint+2010%2C+Managed+Metadata%2C+TaxonomyClientService+in+depth
where are the helper methods (ex: GetListContentTypeGuid) for this article located?
ReplyDeleteSorry I missed it out. I've written another post here:
ReplyDeletehttp://the-simple-programmer.blogspot.com/2011/11/c-function-to-get-content-type-guid.html
Very helpful! Thank you!
ReplyDelete