Tuesday, July 20, 2010

Playing around with the EPiServer.Community.NewsFeed Namespace

 
In EPiServer Relate+, whenever you write a blog post, upload an image or become friends with someone this shows up on an activity feed. We all probably recognize this feature from Facebook, after all this is what Facebook is all about: Seeing what your friends have been up to lately.

When working with the EPiServer.Community.NewsFeed namespace, it’s important to understand the difference between Actor, Action, Target and Story.

Example 1: John uploaded an image
Example 2: John became friends with Sarah

Actor
Who performed the action. John is the actor in both the examples above.

Action
What has been done. In example 1 the action is “uploaded an image” while “became friends with” is the action in example 2.

Target
Who or what was the action done upon? In example 1, the image itself is the target. In example 2, Sarah is the target.

Story
If you put an Actor, an Action and a Target together, you have a Story. Both examples above are stories, the simplest stories we can create. If we want a more complex story we can create stories with multiple actors or targets.

Now how do we do this in code? Let’s assume you have a working Relate+ site. The users of your site will then be actors and the EPiServer Community entities will be your targets (for example blogs, images, users). So we only have to create actions and stories!

Creating, getting and removing actions

Creating an action is very easy, the only thing you need is to find a name for your action and to determine whether the action should be allowed to have multiple actors or targets. Let’s continue our Facebook line of thought and create a “Poke” action:

NewsFeedAction pokeUser = new NewsFeedAction("Poke User");

The action “Poke User” can only have one actor and one target. Let’s create another action “Poke Multiple Users”:

NewsFeedAction pokeMultipleUsers = new NewsFeedAction("Poke Multiple Users", NewsFeedActionCapability.MultipleTargets);

Removing an action is just as easy, first you get the action then you remove it:

NewsFeedAction pokeUser = NewsFeedHandler.GetAction("Poke User"); NewsFeedHandler.RemoveAction(pokeUser);

At last, you can get a collection with all the actions available by calling GetActions():

NewsFeedActionCollection actionCollection = NewsFeedHandler.GetActions();

Creating, getting and removing stories

Let’s create a NewsFeedStory specifying the action, actor and target:

NewsFeedStory story = new NewsFeedStory("Poke User", CurrentUser, null, pokedUser); NewsFeedHandler.AddStoryToActorFeed(story);

The AddStoryToActorFeed adds the story to the actors personal activity feed. In order to get a story you use the NewsFeedHandler.GetStory() method while removing a story can be done by using NewsFeedHandler.RemoveStory():

NewsFeedStory story = NewsFeedHandler.GetStory(1); NewsFeedHandler.RemoveStory(story);

As you can see, the GetStory() method expects you to know the id of the story you want to retreieve. This means that you need to loop through your stories if you don’t know the id. Let’s take a look at how that can be done!

A more complex example

Let’s assume John and Sarah have become friends on your community website. After weeks of cleaning up John’s messy code, Sarah has had enough and decides to delete John as a friend. On a standard installation of Relate+ the friendship will be deleted, but the story will still be visible in the newsfeed. So now we’d like write some code to delete the story from the newsfeed.

First we start off with a simple method called GetSpecificActions() which expects a list of action names. It loops though all the available actions on your site and returns a NewsFeedActionCollection containing all the actions specified in the list:

private NewsFeedActionCollection GetSpecificActions(List<string> includeActions)

{

    NewsFeedActionCollection newsFeedActionCollection = new NewsFeedActionCollection();

    foreach (NewsFeedAction action in NewsFeedHandler.GetActions())

    {

       if (includeActions.Contains(action.Name))

       {

          newsFeedActionCollection.Add(action);

       }

    }

    return newsFeedActionCollection;

}

Next we create a method called DeleteNewsFeedStory():

protected void DeleteNewsFeedStory(IUser actor, IUser target)

{

    List<string> actionList = new List<string> { Properties.Settings.Default.ActionFriendship };

    NewsFeedActionCollection newsFeedActionCollection =  GetSpecificActions(actionList);

    NewsFeedStoryCollection stories = NewsFeedHandler.GetActorFeed(actor, newsFeedActionCollection, DateTime.MinValue, DateTime.Now, 1, 25);

 

     foreach (NewsFeedStory story in stories)

     {

         foreach (IEntity targetEntity in story.Targets)

         {

             IUser user = targetEntity as IUser;

             if (user != null && user.ID == target.ID)

             {

                 NewsFeedHandler.RemoveStory(story);

             }

         }

     }

}

In this method we call GetSpecificActions() and use the NewsFeedActionCollection returned in order to find all Sarah’s stories with action equal to ActionFriendship. We then loop through all the stories and check if the one of the stories has John as a target, and if it does we delete the story.

We could do the exact same thing as we’ve done in this example without specifying the type of action the stories retrieved should have. You’d then get all stories (no matter what action) and you would have to check if the action was correct before removing the story.

Note: This example only shows how to delete the story, the friendship itself is not deleted in this example. I’ve made an assumption that you’ve already deleted the friendship prior to deleting the story :)