Creating Custom Activity feed

Hi all,

SharePoint provide a excellent feature under my site which display the recent activities of the user performed recently using Recent Activities web part and for colleagues activities it provides My newsfeed web part. These web parts will show only those activities which users was configured under "Edit My Profile" page. Following is the screen shot of the Out of box activities feeds.



In order to create the custom activity feed, There are a sample console application provided by the microsoft SDK SharePoint Server 2010: Activity Feeds Console Application just to register the custom activity feed on the server.

Cation: There is no method implemented to delete custom activity once created. So make sure while deploying it on production that you must execute this code of creation once. Only one way to delete the activity feed is from database. For more information visit: Remove Method and Way to Remove Activity Feed

Now I am going to share the code which can be used as a console application as well as in a feature for create a custom activity feed as below:

var context = SPServiceContext.Current;
var pm = new UserProfileManager(context);
var currentUserProfile = pm.GetUserProfile(SPContext.Current.Site.OpenWeb().CurrentUser.LoginName);
var actMgr = new ActivityManager(currentUserProfile, context);
if (actMgr.PrepareToAllowSchemaChanges())
{
ActivityApplication actApplication;
if (actMgr.ActivityApplications["CustomActivity"] == null)
{
actApplication = actMgr.ActivityApplications.Create("CustomActivity");
actApplication.Commit();
actApplication.Refresh(false);
}
else
{
actApplication = actMgr.ActivityApplications["CustomActivity"];
}
ActivityType addDocumentsActivityType = actApplication.ActivityTypes["AddDocuments"];
if (addDocumentsActivityType == null)
{
addDocumentsActivityType = actApplication.ActivityTypes.Create("AddDocuments");
addDocumentsActivityType.ActivityTypeNameLocStringResourceFile = "ActivityResource";
addDocumentsActivityType.ActivityTypeNameLocStringName = "AddDocumentsActivityName";
addDocumentsActivityType.IsPublished = true;
addDocumentsActivityType.IsConsolidated = true;
addDocumentsActivityType.AllowRollup = true;
addDocumentsActivityType.Commit();
addDocumentsActivityType.Refresh(false);
}
ActivityTemplate addDocumentsActTemplate =
addDocumentsActivityType.ActivityTemplates[ActivityTemplatesCollection.CreateKey(false)];
if (addDocumentsActTemplate == null)
{
addDocumentsActTemplate = addDocumentsActivityType.ActivityTemplates.Create(false);
addDocumentsActTemplate.TitleFormatLocStringResourceFile = "ActivityResource";
addDocumentsActTemplate.TitleFormatLocStringName = "Activity_AddComments";
addDocumentsActTemplate.Commit();
addDocumentsActTemplate.Refresh(false);
}
}


Next is to create the resource file. Please follow the instruction given at: http://msdn.microsoft.com/en-us/library/xbx3z216.aspx

Now if you successfully created the activity feed then next step is to create the activity events. Here I am demonstrating the example of the add document event capture and then register it to my custom activity feed.

For this, I need to create a List item event receiver. I will capture the ItemAdding event of the document list and then create a event for the uploaded document.

var documentsListName = SPUtility.GetLocalizedString("$Resources:core,shareddocuments_Title;",
"core",
web.Language);
var pm = new UserProfileManager(SPServiceContext.GetContext(web.Site));
UserProfile currentUserProfile;
try
{
currentUserProfile = pm.GetUserProfile(userName);
PortalLog.LogString("Got user profile: {0}", userName);
SPSecurity.RunWithElevatedPrivileges(() => GrantPermissionsToUserProfileService(userName));
PortalLog.LogString("Permission Granted: {0}", userName);
var actMgr = new ActivityManager(currentUserProfile, SPServiceContext.GetContext(web.Site));
if (string.Equals(listTitle, documentsListName, StringComparison.CurrentCultureIgnoreCase))
{
long activityId =
actMgr.ActivityApplications["CustomActivity"].ActivityTypes["AddDocument"].ActivityTypeId;
if (activityId != 0)
CreateEvent(activityId, currentUserProfile, actMgr, "AddDocument", displayName, itemUrl,
string.Empty);
}
SPSecurity.RunWithElevatedPrivileges(() => RevokePermissionsToUserProfileService(userName));
}
catch (Exception ex)
{
PortalLog.LogString("Error for user: {0}, {1}, {2}", userName, ex.Message,
ex.InnerException);
return false;
private void CreateEvent(long activityId, UserProfile currentUserProfile, ActivityManager actMgr, string activityType, string linkTitle, string linkUrl, string value)
{
PortalLog.LogString("Creating event: {0}", activityType);
Entity publisher = new MinimalPerson(currentUserProfile).CreateEntity(actMgr);
ActivityEvent activityEvent = ActivityEvent.CreateActivityEvent(actMgr, activityId, publisher, publisher);
activityEvent.Name = activityType;
activityEvent.ItemPrivacy = (int)Privacy.Public;
activityEvent.Owner = publisher;
activityEvent.Publisher = publisher;
activityEvent.Value = value;
var link = new Link { Href = linkUrl, Name = linkTitle };
activityEvent.Link = link;
activityEvent.Commit();
PortalLog.LogString("Created event: {0}", activityType);
MulticastPublishedEvents(new List<ActivityEvent> { activityEvent }, actMgr);
}
private void MulticastPublishedEvents(List<ActivityEvent> activityEvents, ActivityManager actMgr)
{
if (activityEvents.Count == 0)
return;
List<long> publishers = activityEvents.Select(e => e.Owner.Id).Distinct().ToList();
Dictionary<long, MinimalPerson> owners;
Dictionary<long, List<MinimalPerson>> colleaguesOfOwners;
ActivityFeedGatherer.GetUsersColleaguesAndRights(actMgr, publishers, out owners, out colleaguesOfOwners);
Dictionary<long, List<ActivityEvent>> eventsPerOwner;
ActivityFeedGatherer.MulticastActivityEvents(actMgr, activityEvents, colleaguesOfOwners, out eventsPerOwner);
List<ActivityEvent> eventsToMulticast;
ActivityFeedGatherer.CollectActivityEventsToConsolidate(eventsPerOwner, out eventsToMulticast);
}
}


There are few more methods which are used to grant the permissions to the user so that they can create the event without any issue. But we must have to revoke that access for other unauthenticated changes.
private static void RevokePermissionsToUserProfileService(string accountName)
{
var upServiceproxy = SPFarm.Local.Services.Where(s => s.GetType().Name.Contains("UserProfileService")).FirstOrDefault();
if (upServiceproxy != null)
{
SPIisWebServiceApplication upServiceApp = upServiceproxy.Applications.OfType().FirstOrDefault();
if (upServiceApp != null)
{
var mgr = SPClaimProviderManager.Local;
var security = upServiceApp.GetAccessControl();
var claim = mgr.ConvertIdentifierToClaim(accountName, SPIdentifierTypes.WindowsSamAccountName);
security.RemoveAccessRule(new SPAclAccessRule(claim,
SPIisWebServiceApplicationRights
.FullControl));
upServiceApp.SetAccessControl(security);
var adminSecurity = upServiceApp.GetAdministrationAccessControl();
var adminClaim = mgr.ConvertIdentifierToClaim(accountName,
SPIdentifierTypes.WindowsSamAccountName);
adminSecurity.RemoveAccessRule(new SPAclAccessRule(adminClaim,
SPCentralAdministrationRights
.FullControl));
upServiceApp.SetAdministrationAccessControl(adminSecurity);
upServiceApp.Uncache();
upServiceproxy.Uncache();
}
}
}
private static void GrantPermissionsToUserProfileService(string accountName)
{
var upServiceproxy = SPFarm.Local.Services.Where(s => s.GetType().Name.Contains("UserProfileService")).FirstOrDefault();
if (upServiceproxy != null)
{
SPIisWebServiceApplication upServiceApp = upServiceproxy.Applications.OfType().FirstOrDefault();
if (upServiceApp != null)
{
var mgr = SPClaimProviderManager.Local;
var security = upServiceApp.GetAccessControl();
var claim = mgr.ConvertIdentifierToClaim(accountName, SPIdentifierTypes.WindowsSamAccountName);
security.AddAccessRule(new SPAclAccessRule(claim,
SPIisWebServiceApplicationRights
.FullControl));
upServiceApp.SetAccessControl(security);
var adminSecurity = upServiceApp.GetAdministrationAccessControl();
var adminClaim = mgr.ConvertIdentifierToClaim(accountName,
SPIdentifierTypes.WindowsSamAccountName);
adminSecurity.AddAccessRule(new SPAclAccessRule(adminClaim,
SPCentralAdministrationRights
.FullControl));
upServiceApp.SetAdministrationAccessControl(adminSecurity);
upServiceApp.Uncache();
upServiceproxy.Uncache();
}
}
}


For more reference :

http://msdn.microsoft.com/en-us/library/ff426884.aspx

http://msdn.microsoft.com/en-us/library/ff426883.aspx

http://msdn.microsoft.com/en-us/library/ff464387.aspx

http://blogs.perficient.com/portals/2011/02/18/sharepoint-2010-activity-feed-explained-part-1/

http://weshackett.com/2011/06/extending-the-activity-feed-with-enterprise-content/

Happy Sharepointing :)

Comments

  1. Hi

    can we hide some of the default activities the user follow .i am trying with client object model but it is updating only for logged in user.

    ReplyDelete

Post a Comment

Popular posts from this blog

Hide Ribbon on SharePoint 2013 using CSS

Get Comment Count in SharePoint

Configure external site as content sources in sharepoint search