пятница, 13 января 2012 г.

Работа с тегами и заметками (комментариями)


Теги и заметки позволяют помечать страницы сайта SharePoint общедоступными соответственно тегами и комментариями.
Данные социальные объекты приписываются к определённому адресу и содержат в себе заголовок (не отображается на сайте), содержимое и владельца (создателя).
Программный доступ к ним осуществляется через объекты SocialTagManager и SocialCommentManager, а также объект SocialRatingManager для рейтинга. Далее будем рассматривать работу с комментариями, работа с тегами и рейтингом реализовывается аналогичным образом.

Получение списка комментариев. Рассмотрим следующий метод:
using (var site = new SPSite(SPContext.Current.Site.ID))
{
    var spServiceContext = SPServiceContext.GetContext(site);
    var socialContextManager = new SocialCommentManager(spServiceContext);
    var comments = socialContextManager.GetComments(new Uri("http://mysite/default.aspx", UriKind.Absolute));
}

Проблемы приведённого кода в том, что он позволяет получить комментарии только определённого пользователя. Для получения всех комментариев всех пользователей для определённого Url необходимо произвести операцию обнуления контекста! Например, следующим образом:
using (var site = new SPSite(SPContext.Current.Site.ID))
{
    var httpContext = HttpContext.Current;
    try
    {
        var spServiceContext = SPServiceContext.GetContext(site);
        var currentWeb = SPContext.Current.Web;
        HttpContext.Current = null; //Обнуляем текущий контекст
        var socialContextManager = new SocialCommentManager(spServiceContext);
        var comments = socialContextManager.GetComments(new Uri("http://mysite/default.aspx", UriKind.Absolute));
    }
    finally
    {
        HttpContext.Current = httpContext; //Восстанавливаем текущий контекст
    }
}

Добавление нового комментария. Пожалуй, единственная операция, которая работает без дополнительных костылей! J
var spServiceContext = SPServiceContext.GetContext(SPContext.Current.Site); //Получение контекста
var socialContextManager = new SocialCommentManager(spServiceContext); //Создание объекта менеджера комментариев
socialContextManager.AddComment(new Uri("http://mysite/default.aspx", UriKind.Absolute), "Мой комментарий!", false, "Заголовок комментария"); //Создание и добавление комментария

Изменение и удаление комментария. Рассмотрим код:
using (var site = new SPSite(SPContext.Current.Site.ID))
{
    var spServiceContext = SPServiceContext.GetContext(site); //Получаем контекст
    var socialContextManager = new SocialCommentManager(spServiceContext);
    var comments = socialContextManager.GetComments(new Uri("http://mysite/default.aspx", UriKind.Absolute)); //Получаем список комментариев

    comments[0].Comment = "Изменённый комментарий"; //Изменяем комментарий
    comments[0].Update(); //Применяем изменения

    comments[1].Delete(); //Удаляем комментарий
}

Проблема данного кода, в том, что таким образом можно удалить только «свои» комментарии, т.е. те которые созданы текущим пользователем. Для удаления комментариев, созданных другими пользователями, необходимо изменить текущего пользователя в контексте. Сделать это можно используя рефлексию:
var siteUrl = SPContext.Current.Site.Url;
using (var site = new SPSite(siteUrl))
{
    var socialCommentManager = new SocialCommentManager(SPServiceContext.GetContext(HttpContext.Current));
    var comments = socialCommentManager.GetComments(CommentsControl.CurrentUri).ToList(); //Получаем список комментариев
    var commentOwner = comments[0].Owner["AccountName"].ToString(); //Получаем логин пользователя создавшего комментарий
   
    using (var web = site.OpenWeb())
    {
        var user = web.EnsureUser(commentOwner);//Получаем нужного пользователя
        web.AllowUnsafeUpdates = true;
        var request = new HttpRequest("", siteUrl, "");
        HttpContext.Current = new HttpContext(request, new HttpResponse(new StringWriter(CultureInfo.CurrentCulture)));
        HttpContext.Current.Items["HttpHandlerSPWeb"] = web;
        var identity = WindowsIdentity.GetCurrent(); //Получаем сущность текущего пользователя
        typeof (WindowsIdentity).GetField("m_name", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(identity, user.LoginName);
        HttpContext.Current.User = new GenericPrincipal(identity, new string[0]); //Изменяем текущего пользователя текущего контекста

        var socialCommentManager2 = new SocialCommentManager(SPServiceContext.GetContext(HttpContext.Current));
        var commentsList = socialCommentManager.GetComments(CommentsControl.CurrentUri).ToList(); //Получаем список комментариев

        commentsList[0].Comment = "Изменённый комментарий"; //Изменяем комментарий
        commentsList[0].Update(); //Применяем изменения

        web.AllowUnsafeUpdates = false;
    }
}

Если нужно изменить/удалить все комментарии всех пользователей, то придётся вызывать вышеприведённый код отдельно для каждого пользователя.

Удачной социализации!