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

Manage comments

Explains how to use ICommentService to manage comments in the Optimizely Community API platform.

In the Optimizely Community API, comments are managed through a service implementing the interface ICommentService. This service provides the ability to persist and retrieve comments that you define.

Access an ICommentService

If the Comments 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 commentService = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<ICommentService>();

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

Example:

var factory = new EPiServer.Social.Comments.DefaultCommentServiceFactory();
var commentService = factory.Create();

Add a comment

You can add a comment by using the Add(Comment) method of the ICommentService. This method accepts an instance of the Comment class and returns a reference to an instance of that class, populated with any additional, system-generated data (for example, a unique ID).

ICommentService commentService;

// ...

var parentContent = Reference.Create("resource://identifier/for/a/resource");
var body = "This is wonderful content!";
var isVisible = true;

var comment = new Comment(parentContent, body, isVisible);

commentService.Add(comment);

The above example invokes the request to add a comment synchronously. Below is an example of adding a comment asynchronously using the asynchronous overload with C#'s async and await keywords.

private async Task<Comment> AddCommentAsync(ICommentService commentService) {
  var parentContent = Reference.Create("resource://identifier/for/a/resource");
  var author = Reference.Create("user://identifier/for/a/user");
  var body = "This is wonderful content!";
  var isVisible = true;

  var comment = new Comment(parentContent, author, body, isVisible);

  var addCommentTask = commentService.AddAsync(comment);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var newComment = await addCommentTask;

  return newComment;
}

Update a comment

You can update a comment that was previously added through the platform by using the Update(Comment) method of the ICommentService. This method accepts a comment, which must be populated with a CommentId that identifies the existing comment.

ICommentService commentService;
Comment existingComment;

// ...

var parentContent = Reference.Create("resource://identifier/for/a/resource");
var author = Reference.Create("user://identifier/for/a/user");
var body = "This is wonderful content!";
var isVisible = true;

var comment = new Comment(existingComment.Id, parentContent, author, body, isVisible);

commentService.Update(comment);

If the comment to be updated does not exist, a CommentDoesNotExistException is thrown.

The above example invokes the request to update a comment synchronously. Below is an example of updating a comment asynchronously using the asynchronous overload with C#'s async and await keywords.

private async Task<Comment> UpdateCommentAsync(ICommentService commentService) {
  Comment existingComment;

  // ...

  var parentContent = Reference.Create("resource://identifier/for/a/resource");
  var author = Reference.Create("user://identifier/for/a/user");
  var body = "This is wonderful content!";
  var isVisible = true;

  var comment = new Comment(existingComment.Id, parentContent, author, body, isVisible);

  var updateCommentTask = commentService.UpdateAsync(comment);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var updatedComment = await updatedCommentTask;

  return updatedComment;
}

Retrieve a comment

To retrieve a specific instance of a comment which was previously added through the platform, use the Get(CommentId) method of the ICommentService. This method accepts an instance of the CommentId class, which identifies the comment to be retrieved. It returns the instance of the Comment class corresponding to that identifier.

ICommentService commentService;
// ...

// Construct a CommentId corresponding to the desired comment
var commentId = CommentId.Create("...");
var comment = commentService.Get(commentId);

If the requested comment cannot be found, a CommentDoesNotExistException is thrown.

The above example invokes the request to retrieve a comment synchronously. An example of retrieving a comment asynchronously using the asynchronous overload with C#'s async and await keywords is described below.

private async Task<Comment> GetCommentAsync(ICommentService commentService) {
  Comment existingComment;
  // ...

  // Construct a CommentId corresponding to the desired comment
  var commentId = CommentId.Create("...");

  var getCommentTask = commentService.GetAsync(commentId);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var comment = await getCommentTask;
  return comment;
}

To retrieve a collection of comments which were previously added through the platform, use the Get(Criteria<CommentFilter>) method. This method accepts an instance of Criteria<CommentFilter>, which contains the specification necessary to retrieve the desired comments.

The Filter property of the Criteria<CommentFilter> class accepts an instance of the CommentFilter class. This class contains specifications that let you refine the result set of comments you want to retrieve.

The properties of the CommentFilter include:

  • Author – Assigning a value (Reference) to this property refines a result set to comments whose author matches the given value.
  • Parent – Assigning a value (Reference) to this property refines a result set to comments that are immediate children of the resource or comments identified by that value.
  • Ancestor – Assigning a value (Reference) to this property refines a result set to comments that are descendants of the resource or comments identified by that value. The identified ancestor may appear anywhere in the lineage of a result (as a parent, grandparent, great-grandparent, and so on).
  • Visibility – Assigning a value (Visibility) to this property refines a result set to comments according to whether or not it is intended to be presented within the application.

The specifications of the CommentFilter may be applied in conjunction with one another. Each specification, which is assigned a value in the filter, further refines the result set (for example, a logical AND). The example below demonstrates the retrieval of a result page of comments, which are immediate children of a particular resource.

ICommentService commentService;
// ...

var parentContent = Reference.Create("resource://identifier/for/a/resource");
var criteria = new Criteria<CommentFilter> {
  Filter = new CommentFilter {
    Parent = parentContent
  }
};
var pageOfComments = commentService.Get(criteria);

In the next example, a similar approach is taken to demonstrate the retrieval of a result page of comments, which are descendants of a particular comment.

ICommentService commentService;
CommentId idOfExistingComment;
// ...

var ancestralComment = idOfExistingComment.ToReference();
var criteria = new Criteria<CommentFilter> {
  Filter = new CommentFilter {
    Ancestor = ancestralComment
  }
};
var pageOfContents = commentService.Get(criteria);

In the above example, the request to retrieve comments is invoked synchronously. An example of retrieving comments asynchronously using the asynchronous overload with C#'s async and await keywords is described below.

private async Task<ResultPage<Comment>> GetCommentsAsync(ICommentService commentService) {
  // ...

  var parentContent = Reference.Create("resource://identifier/for/a/resource");
  var criteria = new Criteria<CommentFilter> {
    Filter = new CommentFilter {
      Parent = parentContent
    }
  };
  var getCommentsTask = commentService.GetAsync(criteria);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var pageOfComments = await getCommentTask;
  return pageOfComments;
}

Sort comments

The CommentSortFields class exposes a set of fields upon which a result set of comments may be ordered. These fields may be applied when constructing sorting rules you associate with your criteria. These fields include:

  • CommentSortFields.Id
  • CommentSortFields.Created
  • CommentSortFields.Author

The example below demonstrates the application of sorting rules to order a result set by comment creation date, from oldest to newest.

var criteria = new Criteria<CommentFilter> {
  OrderBy = new List<SortInfo> {
    new SortInfo(CommentSortFields.Created, true)
  }
};

Remove a comment

You can remove a comment by using the Remove(CommentId) method of the ICommentService. This method accepts an instance of the CommentId class. It is important to consider that when a comment is deleted, the descendants of that comment are also deleted. When a comment is deleted, the parent comment of the deleted comment is updated with the corrected HasChildren and HasVisibleChildren properties. When a comment is deleted, the corresponding extension data is removed from the system.

ICommentService commentService;
// ...

var commentId = CommentId.Create("resource://identifier/for/a/resource");
commentService.Remove(commentId);

The above example invokes the request to remove a comment synchronously. The following example removes a comment asynchronously using the asynchronous overload with C#'s async and awaits keywords.

private async Task RemoveCommentAsync(ICommentService commentService) {
  // ...

  var commentId = CommentId.Create("resource://identifier/for/a/resource");
  commentService.Remove(commentId);
  var removeCommentTask = commentService.RemoveAsync(criteria);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  await removeCommentTask;
}

For details regarding criteria use, including information on paging and sorting, see Criteria in Discover the platform.

Best practices to manage comments

Comments, by nature, are a unique form of content. Generally, there is a high frequency of publication and a high frequency of reads. With this in mind, applications should avoid unnecessarily escalating the frequency and volume of those operations.

Page result sets

Paging is an essential strategy in managing your application's performance. It lets you limit the volume of a result set by requesting comments in batches. Studies have found that viewers often don't read beyond the first few comments. So, limit result pages to 5-10 results and prompt users to reveal more. Limiting pages to a size that is proportionate to your audience's reading habits minimizes the performance impact of transferring results. For information on paging result sets, see PageInfo in Discover the platform.

Display replies on demand

You can further reduce the volume of result sets by prompting users to reveal replies when they are interested in digging deeper into a thread. The Optimizely Community API lets you retrieve comments that are immediate children of a parent comment. If users choose to view a comment's replies, use this mechanism to reveal the next level of the comment tree.

Render comments optimistically

A common approach to optimizing applications is to perform actions optimistically, assuming a positive outcome for an action without waiting for it to complete.

As you implement user experiences for publishing comments, consider presenting a comment optimistically. If a user composes a comment, the application asynchronously publishes it through the platform, and the user interface is updated immediately. In doing so, your application provides instant user feedback while avoiding a roundtrip to the platform to retrieve a largely redundant page of comments.

Cache comments

Comments are often contributed to an application with significant frequency. However, they are not particularly volatile because they are not often updated or edited. Employing a caching strategy for comments within your application can be advantageous in reducing the volume of requests for retrieval to the platform.