It is a common requirement in the enterprise social scenarios, to post on to SharePoint newsfeed on behalf on someone else. Those reasons are mainly in the domain of the social governance, or implementing internal procedures. Just think of automatic admin posts to the site feeds, in the case of important breaches of internal procedures. Or, think of a common practice of posting as bot user on personal feed – let’s say, there is a bot CRM user, which automatically posts to it’s newsfeed all important sales events which are coming from the CRM system.
SharePoint 2013 client object model does not give us an opportunity to post on behalf of someone else. For this purpose, we need to use SharePoint 2013 server object model, which is all but good documented (at least at the moment).
For this purpose, we will make an use of few classes from the “Microsoft.Office.Server.Social” namespace.
SPSocialFeedManager is the class which contains most important methods for manipulating feeds for any user. SPSocialPostCreationData contains information about a single post. SPSocialDataItem contains information about social actors associated with a social post. With SPSocialAttachment, we can add attachments to social posts. And if you would like to specify your own application as a poster to the newsfeed (something like “Posted by my cool app”), you will make a use of the SPSocialLink class.
Since all this is happening in an user context, we will need to use UserProfileManager from the Microsoft.Office.Server.UserProfiles namespace.
For this to work, it is important to remember the feed structure – I was writing about it in one of my pervious posts:
Any feed – personal or site feed – contains a number of threads. Each thread contains an array of social actors. It is very important that those actors are found in array in that particular order, in which they appear in the thread. That order is the only way for SharePoint 2013 feed to know which social actor comes at which position inside the thread. Each thread contains at least one root post, and any number of replies. Post – root or reply – contain info about the author, likes, post body, and eventual attachments.
So let’s look how does it work in practice.
Please take a look at the code below, the whole thing is explained in the inline comments (that’s where it belongs, anyway )
using (SPSite site = new SPSite(contextSiteName)) { string username = "sharedove\someuser"; SPServiceContext context = SPServiceContext.GetContext(site); UserProfileManager profileManager = new UserProfileManager(context); if (profileManager.UserExists(username)) { UserProfile userProfile = profileManager.GetUserProfile(username); } else { // Oops. User that you want to post on behalf of, can not be found // You would do something really clever here in production. return; } //get the Social Feed Manager in the context of the requested user SPSocialFeedManager feedManager = new SPSocialFeedManager(userProfile, context); //Create SPSocialPostCreationData object for a new social post SPSocialPostCreationData postCreationData = new SPSocialPostCreationData(); //set the body of the post. Note the arguments, and their order. postCreationData.ContentText = "Hello, the user {0} is going to be mentioned here. We will also have a link {1}, and a tag {2}"; //now we need to add the social actors (SPSocialDataItem), in the same order we have the arguments in the post body: //let's first mention an user SPSocialDataItem socialDataMentionItem = new SPSocialDataItem(); socialDataMentionItem.ItemType = SPSocialDataItemType.User; socialDataMentionItem.AccountName = "sharedove\mentionedUser"; //Add mention to the PostCreationDataContentItems Array.Resize(ref postCreationData.ContentItems, postCreationData.ContentItems.Length + 1); postCreationData.ContentItems[postCreationData.ContentItems - 1] = socialDataMentionItem; //Next, add a link as SPSocialDataItem to the postCreationData SPSocialDataItem socialDataLinkItem = new SPSocialDataItem(); socialDataLinkItem.ItemType = SPSocialDataItemType.Link; socialDataLinkItem.Text = "Adis Jugo Blog"; socialDataLinkItem.Uri = new Uri("https://blog.sharedove.com/adisjugo/"); //Add social link item to the PostCreationDataContentItems Array.Resize(ref postCreationData.ContentItems, postCreationData.ContentItems.Length + 1); postCreationData.ContentItems[postCreationData.ContentItems - 1] = socialDataLinkItem; //As the last (third) social item, add a tag string myTag="#blogpost"; //Now, since the hashtags are actually stored in the TermStore (Managed Metadata Service), in order this to work, //we need to add our tag there: SPSecurity.RunWithElevatedPrivileges(delegate { using (SPSite elevatedSiteCollection = new SPSite(site.ID)) { TermSet settingsTermSet = null; //create a taxonomy session TaxonomySession session = new TaxonomySession(elevatedSiteCollection, true); // obtain the term store TermStore store = session.DefaultSiteCollectionTermStore; //get the groups GroupCollection groups = store.Groups; // get the System taxonomy group Group settingsGroup = store.Groups.Where(x => x.Name == "System").FirstOrDefault(); //get the Hashtags termset hashTermSet = settingsGroup.TermSets.Where(x => x.Name == "Hashtags").FirstOrDefault(); //and now, try to get our tag from the termset hashtagTerm = hashTermSet.Terms.Where(x => x.Name == myTag).FirstOrDefault(); //or create it if it does not exist if (hashtagTerm == null) { hashtagTerm = hashTermSet.CreateTerm(termName, hashTermSet.TermStore.DefaultLanguage); hashtagTerm.IsAvailableForTagging = true; // commit it all hashTermSet.TermStore.CommitAll(); } } }); // Now, when we have a hashtag term, let's add it to the social post SPSocialDataItem socialDataTagItem = new SPSocialDataItem(); socialDataTagItem.ItemType = SPSocialDataItemType.Tag; socialDataTagItem.Text = tag; socialDataTagItem.TagGuid = hashtagTerm.Id; //Add the tag to the PostCreationDataContentItems Array.Resize(ref postCreationData.ContentItems, postCreationData.ContentItems.Length + 1); postCreationData.ContentItems[postCreationData.ContentItems - 1] = socialDataTagItem; //On the end, add an attachemt to the social post string attachment = "http://mysite/photo.jpg"; SPSocialAttachment statusAttachment = new SPSocialAttachment(); //Now, determine the attachment type. SharePoint will display on different ways videos, photos, and images attachments. if (attachment.ToUpper().EndsWith("JPG") || attachment.ToUpper().EndsWith("JPEG") || attachment.ToUpper().EndsWith("PNG") || attachment.ToUpper().EndsWith("GIF")) { statusAttachment.AttachmentKind = SPSocialAttachmentKind.Image; } else if (attachment.ToUpper().EndsWith("WMV") || attachment.ToUpper().EndsWith("MP4") || attachment.ToUpper().EndsWith("AVI") || attachment.ToUpper().EndsWith("MPEG")) { statusAttachment.AttachmentKind = SPSocialAttachmentKind.Video; } else { statusAttachment.AttachmentKind = SPSocialAttachmentKind.Document; } statusAttachment.Uri = new Uri(attachment); statusAttachment.Name = "Look here"; postCreationData.Attachment = statusAttachment; //set the posting "app" (actually, anything can go here); postCreationData.Source = new SPSocialLink() { Uri = new Uri("http://blog.sharedove.com"), Text = "ShareDove cool social app"}; //create the post in feed of the user, in whose context we have created SPFeedManager. //That's why we leave null here. feedManager.CreatePost(null, postCreationData); //For the site feed, we would put SharePoint site in the CreatePost: feedManager.CreatePost("http://sharepointserver/sites/somesite/", postCreationData); }