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