Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

HomeDev GuideRecipesAPI Reference
Dev GuideAPI ReferenceUser GuideLegal TermsGitHubNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Activities

Describes the activities feature of the Optimizely Community API.

Activities signify an event or action occurring within your application. The Optimizely Community API lets activities publish within an application, generating corresponding feed items for subscribing users. It also lets your application react to these activities in real-time.

An activity is represented in the system using the Activity class.

Identify an actor and target

An Activity identifies an actor and a target:

  • Actor – User who triggered activity.
  • Target – Resource or user upon which the activity occurred.

The actor is identified with an instance of the Reference class.

The target is also identified with an instance of the Reference class, which may represent a resource, such as a page, product, or user within your application.

The scheme to define these targets and references is designed within your application.

For information on constructing References, including best practices, see References and IDs in Discover the platform.

Design an activity

The Activity Streams feature leverages the platform's concept of Composites, providing developers with complete control over the design of their application's activities.

Activities published within the platform are accompanied by data on your design. This data, intended to encapsulate information defining the particular activity that occurred, is available upon retrieval of feeds for subscribing users.

For example, an application wants to announce to interested users whenever a product is rated. The application adds an activity representing this action through the Activity Streams system, resulting in the generation of feed items for subscribing users and the notification of handlers registered to react to the event in real time.

An example of a class definition representing the activity of rating a page appears below.

public class PageRated {
  public int Rating {
    get;
    set;
  }
  public string UserName {
    get;
    set;
  }
  public string PageId {
    get;
    set;
  }
  public string PageName {
    get;
    set;
  }
}

For information and best practices on designing such types, see Defining extension data in Discover the platform.

Manage activities

In the Optimizely Community API, activities are managed through a service implementing the interface IActivityService. This service provides the ability to add and respond to activities in your application.

Access an IActivityService

When the Activity Streams feature is installed on an Optimizely Content Management System (CMS) site, with the feature's site integration package, you can get an instance of this service from the inversion of control (IoC) container.

Example:

var activityService = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<IActivityService>();

When the feature is installed on a non-Optimizely CMS site, you can get an instance of a service from the default factory class provided within the package.

Example:

var factory = new EPiServer.Social.ActivityStreams.DefaultActivityStreamsFactory();
var activityService = factory.CreateActivityService();

Add an activity

You can publish an activity to the Optimizely Community Activity Streams system by using the Add<TExtension>(Activity,TExtension) method of the IActivityService. This method accepts an instance of the Activity class and an instance of TExtension. TExtension is a type defined within your application used to describe the activity that occurred.

When the system receives an activity, it scans existing subscriptions to identify subscribers interested in the received activity. The system generates a feed item for eligible subscribers if matching subscriptions are found.

A feed item is generated for:

  • Any subscription following the target of the activity.
  • Any subscription following the actor who performed the activity.

Adding an activity also results in the notification of any handlers registered to watch for activities of the type represented by TExtension.

Adding an activity is a non-blocking operation. The activity is queued, and control is immediately returned to your application. The generation of feed items is not instantaneous; the items are generated as the system can process them.

The example below demonstrates the announcement of the contribution of a rating to a page, using the PageRated definition described in Designing an activity.

IActivityService activityService;
// ...

var actingUser = Reference.Create("user://identifier/for/a/user");
var pageActedUpon = Reference.Create("resource://identifier/for/a/resource");
var activity = new Activity(actingUser, pageActedUpon);
var payload = new PageRated {
  Rating = 1,
    UserName = "Rater",
    PageId = "/My/Page",
    PageName = "My Page"
};
activityService.Add(activity, payload);

The next example uses a similar approach to add an activity targeting a user. Consider an activity using the Vote definition described below:

public class Vote {
  public int Rating {
    get;
    set;
  }
  public String Candidate {
    get;
    set;
  }
  public String Voter {
    get;
    set;
  }
}

To add an activity whereby the user "Chris" votes for the user "Carlos," consider the sample below:

IActivityService activityService;
// ...

var actingUser = Reference.Create("user://identifier/for/a/user");
var userActedUpon = Reference.Create("user://identifier/for/another/user");
var activity = new Activity(actingUser, userActedUpon);
var payload = new Vote {
  Rating = 10,
    Candidate = "Carlos",
    Voter = "Chris",
};
activityService.Add(activity, payload);

Watch activities

In addition to generating feed items, the Activity Streams feature handles activity notifications. A developer may register a handler, which the platform invokes upon receipt of activities the handler can process.

You register a handler to receive activity notifications for a particular type of activity by using the Watch<TExtension>(IActivityHandler) method. The method accepts an instance of IActivityHandler<TExtension>, defining the operation to be executed when an activity is received. The type parameter, TExtension identifies the type of activity payload the handler can handle.

The execution of handlers is not an instantaneous operation. Their execution does not block a request; they are executed as the system can process them. The order of handler execution is not guaranteed. Implement handlers so that their behavior is not dependent on the execution of another handler.

The example below demonstrates an implementation of IActivityHandler for the PageRated activity, which is defined in previous examples.

public class PageRatedActivityHandler: IActivityHandler<PageRated> {
  public void Handle(Activity activity, PageRated extension) {
    // Note: This example leverages the Optimizely LogManager.

    LogManager.GetLogger().Debug(
      "PageRated activity received. Actor: {0} Date: {1} Payload: PageName: {2} UserName: {3}",
      activity.Actor.ToString(),
      activity.Created.ToString(),
      extension.PageName,
      extension.UserName
    );
  }
}

An instance of this handler can be registered to receive a notification upon receipt of PageRated activities, as shown below.

IActivityService activityService;

// ...

activityService.Watch(new PageRatedActivityHandler());

A handler only needs to be registered once in the lifecycle of your application, typically during application startup or initialization. (Registering the same handler multiple times results in multiple invocations of that handler for a single activity.)

If registering a handler in an Optimizely site, you could use an initialization module to perform this setup.

Best practices for watching activities

Stateless operations

It is important to consider that handlers are executed within the context of your application. It is advantageous to implement handlers as stateless operations to account for the possibility that instances of your application may be distributed.

Short-lived operations

The execution of a handler occurs in the background and does not block the execution of the thread in which an activity is being added to the system. However, the execution of one handler may block the execution of subsequent handlers. It is recommended that handlers registered to watch activities execute only short-lived operations. Longer-running operations should be offloaded to services or systems that are more suitable to accommodate them.