пятница, 21 января 2011 г.

SharePoint 2010: How to work with Taxonomy Fields using Client Object Model

Продолжу тему работы с Managed Metadata полями в SharePoint 2010, затронутую в прошлом посте.

Если посмотреть внутрь TaxonomyField, то оказывается, что это почти обычный LookUpField, который ссылается на скрытый лист TaxonomyHiddenList, живущий в рутовом сайте по адресу http://server/Lists/TaxonomyHiddenList. Этот лист содержит все Term'ы, которые использовались в данной коллекции. Хочу особо подчеркнуть, что именно использовались, т.к. если Term был добавлен, но ни разу не использовался в этом листе его не будет. Создается, он автоматически, при вызове метода SetFieldValue()()

К сожалению, Client Object Model ничего не знает о типах TaxonomyField и TaxonomyFieldValue и всем прочем, что находится в сборке "Microsoft.SharePoint.Taxonomy.dll". И как следствие полноценная работа с Taxonomy через Client OM невозможна.

Но не все так уж плохо. TaxonomyFieldValue имеет строковое представление, очень похожее на строковое представление LookUp полей:

5;#SuperNewTerm|f8b19ce9-ea14-4831-8284-e230026e6476

и следовательно его можно установить через Client OM, используя вот такой код:

var webUrl =  "http://server";
using (var clientContext = new ClientContext(webUrl))
{
    var itemCreation = new ListItemCreationInformation();
    itemCreation.UnderlyingObjectType = FileSystemObjectType.File;
    var lst = clientContext.Web.Lists.GetByTitle("TaxList");
    var item = lst.AddItem(itemCreation);
    item["Title"] = "Csom created";
    item["MyTerm"] = "5;#SuperNewTerm|f8b19ce9-ea14-4831-8284-e230026e6476";
    item.Update();
    clientContext.ExecuteQuery();
}
 

Сложность состоит в том, что при начальном формировании TermSet'ов TaxonomyHiddenList пуст. Но покопавшись в коде TaxonomyField.SetFieldValue() я нашел способ заполнения этого листа без непосредственного создания ссылающихся item'ов. К сожалению делать это приходится используя Server OM.

var url = "http://server/Lists/TaxList";
using (var site = new SPSite(url))
{
    using (var web = site.OpenWeb())
    {
        var lst = web.GetList(url);
        var taxfld = lst.Fields["MyTerm"] as TaxonomyField;
        var tSes = new TaxonomySession(site);
        var tStore = tSes.TermStores[taxfld.SspId];
        var tSet = tStore.GetTermSet(taxfld.TermSetId);
        foreach (var term in tSet.Terms)
        {
            int effectiveLcid = tStore.DefaultLanguage;
            string text = term.GetDefaultLabel(effectiveLcid) + TaxonomyField.TaxonomyGuidLabelDelimiter + term.Id;
            var tv = new TaxonomyFieldValue(taxfld);
            tv.PopulateFromLabelGuidPair(text);
        }
    }
}
 

После того как все Term'ы пред созданы с ними можно работать через Client OM.

PS: Только не забывайте что Term'ы могут содержать внутри себя другие Term'ы, и в моем коде, для простоты, это не учтено. :)

Комментариев нет: