Hide menu Last updated: Jun 01 2017
Area: Episerver Social Applies to versions: 1.4 and higher
Other versions:

Managing comments

In the Episerver Social platform, comments are managed through a service implementing the interface ICommentService. This service provides the ability to persist and retrieve comments that you define.

Accessing an ICommentService

If the Comments feature is installed to an Episerver 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 to a non-Episerver CMS site, you can get an instance of this service from the default factory class provided within the package.

Example:

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

Adding 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 a new instance of that class, which is 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);

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

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;
}

Updating a comment

You can update a comment which 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.

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

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;
}

Retrieving 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.

In the above example, the request to retrieve a comment is invoked 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;
}

Sorting comments

The CommentSortFields class exposes a set of fields upon which a result set of comments may be ordered. These fields may be applied in the construction of sorting rules that 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)
    }
};

Removing 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 all of 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 also removed from the system.

ICommentService commentService;

// ...

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

commentService.Remove(commentId);

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

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 more details regarding the use of criteria, including information on paging and sorting, see Criteria.

Best practices for managing comments

Comments, by nature, are a unique form of content. Generally, there is a high frequency of publication as well as 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. By limiting pages to a size that is proportionate your audience's reading habits, you minimize the performance impact of transferring results. For more information on paging result sets, see PageInfo.

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 Episerver Social platform 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, that is, assume a positive outcome for an action without waiting for it to complete.

As you implement user experiences for publishing comments, consider presenting a new comment optimistically. That is, if a user composes a new 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 a particularly volatile form of content as they are not often updated or edited. It can be advantageous to employ a caching strategy for comments within your application, to reduce its volume of requests to the platform for retrieval.

Comments