Carlos Colon
Mar 3, 2017
  3544
(8 votes)

Building a Like button with Episerver Social Ratings

Overview

In this tutorial, we are going to show how to build a Like button with the Episerver Social Ratings service API [1]. A Like button has a few simple requirements:

  • Track the total number of times the Like button was clicked.
  • Determine if a user with a known identity has already Liked the page.

For the purposes of this tutorial and to keep the implementation simple, the tutorial code will let anonymous users rate as many times as they choose. The full source code for the tutorial is available in our SocialAlloy github.com repo [2].

Prerequisites

To use the Social Ratings service API, install the EPiServer.Social.Ratings NuGet package, available in the Episerver NuGet feed [4], to your project or solution. If using the Social Ratings service API in an Episerver site, you should also install the EPiServer.Social.Ratings.Site package to leverage Episerver’s ServiceLocator container to create the Social Ratings service instance. The SocialAlloy repo [2] already has these packages installed and will be restored when the solution is built.

Building the Like button

Keep in mind that the full source in the SocialAlloy repo [2] is for educational purposes and is not production quality. As implemented, the Like button has the following components: 

1.     An Episerver Block

A block is used to add a Like button to any page in the SocialAlloy site.

2.     A Like button controller

The Like button controller is the business logic implementation of the Like button functionality. The controller has three public methods: 

  • Constructor method – In the constructor, global resources needed by other public methods are allocated. The controller needs an instance of the ratings service to be able to retrieve and save Like ratings. Installing the EPiServer.Social.Ratings.Site package enables the use of Episerver’s ServiceLocator to allocate that instance.
this.ratingService = ServiceLocator.Current.GetInstance<IRatingService>();
  • Index method – This method contains the business logic that renders the block’s front end view in whatever page the block is currently executing on. As for the ratings API usage, the critical parts of this method are: 
    • Get the rating for a user with an identity (does not apply to anonymous users). The rating filter is supplied with a user rater and page target references. Since a count of only one item is expected to match the criteria, we specify a PageSize of one. 
var ratingPage = ratingService.Get(
        new Criteria<RatingFilter>
        {
               Filter = new RatingFilter
               {
                       Rater = raterUserRef,
                       Targets = new List<Reference>
                       {
                              targetPageRef
                       }
               },
               PageInfo = new PageInfo
               {
                       PageSize = 1
               }
        }
);
    • Get Like statistics for the current page. We are interested in the total number of Likes the current page has received across all users. 
var ratingStatisticsPage = ratingService.Get(
               new Criteria<RatingStatisticsFilter>
               {
                              Filter = new RatingStatisticsFilter
                              {
                                             Targets = new List<Reference>
                                             {
                                                            targetPageRef
                                             }
                              },
                              PageInfo = new PageInfo
                              {
                                             PageSize = 1
                              }
               }
);
  • Submit method – This method contains the business logic that handles a user clicking the Like button in the block’s front end view in whatever page the block is currently executing. As for the rating API usage, the critical functionality of this method is to use the rating service Add API to save the Like for the user (rater) and the current page (target). Because Like is a very simple rating, we store the rating as Liked_Rating = 1.
var addedRating = ratingService.Add(
               new Rating(
                              raterUserRef,
                              targetPageRef,
                              new RatingValue(Liked_Rating)
               )
)

3.     A Like button block front end view model

The controller needs to provide data to the Like button view. We need a model to store that data, so the view can access it while it is rendered. The Like button block view model is implemented as follows: 

public class LikeButtonBlockViewModel
{
        public LikeButtonBlockViewModel(){}

        public PageReference PageLink { get; set; }

        public long TotalCount { get; set; }

        public int? CurrentRating { get; set; }
}

The empty constructor is required by the CMS framework, since it needs to create the model when the block view form is submitted back to the server. We also need the reference to the current page for use by the Like button click handler on the server side. The TotalCount and the CurrentRating are rating specific properties.

  • TotalCount stores the total count of clicks across all users.
  • CurrentRating stores the Like rating (i.e., Liked_Rating) for the current user, if any.

4.     A Like button view

The Like button block needs a view to render itself in the front end. That view is implemented as follows: 

<div class="border">
    <div style="margin-top:0.5em">
        @if (Model.CurrentRating.HasValue)
        {
            <div> You have already <i class="icon-thumbs-up"></i> this page! </div>
        }
        else
        {
            using (Html.BeginForm("Submit", null))
            {
                @Html.HiddenFor(m => m.PageLink)
                <div>
                    <button name="submitsocialrating" value="Submit" class="btn-primary"><i class="icon-thumbs-up"></i> Like </button>
                </div>
            }
        }
        <br/>
        <div><strong>Likes: @Model.TotalCount</strong></div>
    </div>
</div>

If there is a rating value for the current user, meaning the user has previously Liked the page, then the view reflects that. In that case, do not allow the current user to Like the page again by not displaying the Like button.

If there is no Like rating value for the current user, which is always the case for anonymous users, then display the Like button. Finally, the view shows the total count of Likes for the page across all users.

References

[1] Episerver Social Developer Guide -- http://world.episerver.com/documentation/developer-guides/social/ 

[2] Full tutorial code:

Block: https://github.com/episerver/SocialAlloy/tree/master/src/EPiServer.SocialAlloy.Web/Social/Blocks/Ratings/LikeButtonBlock.cs

Controller: https://github.com/episerver/SocialAlloy/tree/master/src/EPiServer.SocialAlloy.Web/Social/Controllers/LikeButtonBlockController.cs

Model: https://github.com/episerver/SocialAlloy/tree/master/src/EPiServer.SocialAlloy.Web/Social/Models/Ratings/LikeButtonBlockViewModel.cs

[3] Tutorial code views -- https://github.com/episerver/SocialAlloy/tree/master/src/EPiServer.SocialAlloy.Web/Views/Social 

[4] Episerver NuGet feed -- http://nuget.episerver.com/feed/packages.svc

Mar 03, 2017

Comments

Please login to comment.
Latest blogs
Searchable settings page

In my current project which has been actively developed for quite some time we have a big classic settings page. Unfortunately the placement and...

Per Nergård (MVP) | Apr 6, 2026

Using Azure Devops Pipelines in Optimizely SAAS (Configured) Commerce

Introduction When working with SAAS Commerce build service v2 your currently need to use a github repo with configured branches to start deployment...

Mark Hall | Apr 4, 2026 |

Forcing Lowercase URLs in Optimizely CMS During Auto-Translation

Learn how to fix uppercase and punctuation issues in Optimizely CMS 12 URL segments caused by LanguageManager auto-translation using a custom...

Stuart | Apr 2, 2026 |

Stott Robots Handler v7 for Optimizely CMS 13

Stott Robots Handler version 7 is now available for  Optimizely PaaS CMS 13 . This is includes updates to support the switch from a Site based...

Mark Stott | Apr 2, 2026

Optimizely CMS 13 First Impressions

Introduction This week Optimizely released the long awaited CMS 13. I upgraded my Optimizely extensions package to CMS 13 and found some interestin...

Mark Hall | Apr 2, 2026 |

Automating Block Translations in Optimizely

Stop manual block-by-block translations. Learn how to use the TranslateOrCopyContentAreaChildrenBlockForTypes config to automate Optimizely CMS...

Stuart | Apr 1, 2026 |