Back to Insights

Calling the Rating Service using jQuery in SharePoint 2010 Part 1 of 2

On a recent project we were tasked with creating a way for users on the intranet to cast a vote either up or down on a blog post. With SharePoint 2010 having an out of the box rating system, we decided that we should leverage this system.

Out-of-the-box, the rating system allows a user to cast a vote between 1 and 5, in fact, if your vote is outside of these values then the service will throw an exception. When the vote is stored in the db, it seems that it is multiplied by 20 and stored out of 100. So a vote of 5 is stored as 100 and a vote of 1 is stored as 20.

Please note that from here on I've made an assumption that you are familiar with jQuery and calling web services as well as how to deploy a custom solution to SharePoint

The ratings web service that you want to call for any ratings related operations is found  at http://yoursite/_vti_bin/SocialDataService.asmx

If you go to this URL, you will see many methods available for us to call, we were interested in only two of them though.

  • SetRating
  • GetRatingOfUserOnUrl

With these two methods we can cast a vote and check if the current user has voted for the item already. This service can be called using JSON objects or using SOAP calls, we decided on JSON objects as we wanted to do client side calls using jQuery.

Here is what we are hoping to accomplish:

  1. When the page loads, we check to see if each item has been voted for by the current user
  2. If they have not voted, we present a nice set of vote up / down icons
  3. If they have voted, we display the disabled buttons that indicate which way the user voted
  4. When the user votes, the icons are reset to the disabled state indicating which way the user voted

The first thing we did was to define the HTML and CSS classes we would be targeting with our plugin. Here is a snippet of the html.

<div class="sv-Rating">
<ul class="sv-VoteControls">
<div class="sv-VoteUp sv-VoteButton"> </div>
<li class="sv-VoteControlsLast">
<div class="sv-VoteDown sv-VoteButton"></div>
<a class="sv-ItemLink">Item Link</a>


The next thing we created was a jQuery Plugin. The JavaScript for this plugin lives in it's own file called RatingControl.js. It will need to be registered on the page at pre-render. We'll get into that a bit later.

Here is our jQuery Plugin. I'll walk through how it works below.

/* ----------------------------------------------------------------------
jQuery plug-in pattern

jQuery Authoring Guidelines

---------------------------------------------------------------------- */

// create anonymous function closure
(function ($) {
    // .. 

    /* ------------------------------------------------------

    plugin definition

    ------------------------------------------------------ */

    /// Rating Jquery Plugin
    $.fn.RatingControl = function (options) {

        // build main options before element iteration
        var opts = $.extend({}, $.fn.RatingControl.defaults, options);

        // Returns the element collection. Chainable.
        return this.each(function () {
            var $this = $(this);

            // build element specific options, compatible with Metadata Plugin
            var o = $.meta ? $.extend({}, opts, $ : opts;

            init(o, $this);

    /* ------------------------------------------------------

    	define and expose public methods

    	------------------------------------------------------ */
    $.fn.RatingControl.VoteUp = function (opts, $obj) {
        lastVote = 5;
        Vote(opts, $obj, 5);

    $.fn.RatingControl.VoteDown = function (opts, $obj) {
        lastVote = 1;
        Vote(opts, $obj, 1);

    /* ------------------------------------------------------

	private functions and variables

	------------------------------------------------------ */
    var lastVote = -1;

    // add click event handler to elements
    function init(opts, $obj) {
        CheckVote(opts, $obj);

    // call service
    function CallService(opts, $obj, serviceData, callBack) {
            type: "POST",
            url: serviceData.ServiceUrl,
            data: $.toJSON(serviceData),
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (data) {
                //.. do something with data
                callBack(data, $obj, opts);
            error: function (XMLHttpRequest, textStatus, errorThrown) {

    function Vote(opts, $obj, rating) {
        var serviceData = new Object();
        serviceData.url = $('.sv-ItemLink', $obj).attr('href');
        serviceData.rating = rating;
        serviceData.title = '';
        serviceData.analysisDataEntry = new Object();
        serviceData.RatedAssetId = serviceData.url;

        serviceData.ServiceUrl = opts.SetRatingUrl;
        CallService(opts, $obj, serviceData, VoteSucceeded);

    function CheckVote(opts, $obj) {
        var serviceData = new Object();
        serviceData.url = $('.sv-ItemLink', $obj).attr('href');
        if (serviceData.url != null) {
            serviceData.userAccountName = opts.CurrentUser;

            serviceData.ServiceUrl = opts.GetRatingUrl;
            CallService(opts, $obj, serviceData, GetRatingSucceeded);

    function VoteSucceeded(result, $obj, opts) {
        CheckVote(opts, $obj);

    function GetRatingSucceeded(result, $obj, opts) {
        //set appropriate style
        var isVoted = false;
        var rating = result.d.Rating;

        if (rating > 0) {
            isVoted = true;

        if (isVoted) {
            SetVotedState(rating, $obj);
        } else {
            SetNotVotedState($obj, opts);


    /* ------------------------------------------------------

	exposed plugin default properties or options

	------------------------------------------------------ */
    $.fn.RatingControl.defaults = {
        ServiceUrl: '/_vti_bin/SocialDataService.asmx/',
        SetRatingUrl: '/_vti_bin/SocialDataService.asmx/SetRating',
        GetRatingUrl: '/_vti_bin/SocialDataService.asmx/GetRatingOfUserOnUrl'

    // end of closure

First, let's look at what data we need to send to each method on the web service.

In order to check if the current user has voted, we'll need:

  1. The User's Active Directory username (i.e. DOMAIN\user)
  2. The URL to the item we are rating — this should be the URL to the list item, not the URL to the current page.

In order to vote, we need to send at a minimum:

  1. The User's Active Directory username (i.e. DOMAIN\user)
  2. The URL to the item we are rating — this should be the URL to the list item, not the URL to the current page.
  3. The rating (1-5)
  4. A title (we sent a blank string, without this the service throws a 500 error)
  5. The Rated AssetId (again, this is the URL to the list item)

When the page first loads and our plugin is registered, it looks for each voting control on the page (there may be more than one) and sets up the voting buttons. First it calls CheckVote. This function creates a JavaScript object with the needed data and the service URL and fires our CallService function. 

You'll notive a variable called "opts" throughout the plugin, this is used to pass options into the plugin and from function to function as needed. For instance, when we register the plugin on the page, we'll pass in the current user's username.

CallService registers a callback function to be called if the web service call succeeds. For CheckVote, we want to call GetRatingSucceeded on success. This method checks the result of the web service call to determine if the current user has previously voted and set's the appropriate classes and click handlers based on the result using the SetVotedState and SetNotVotedState methods.

When one of the voting buttons is enabled in the Votable state and it is clicked, first the Vote function is called in the same manner as the CheckVote method was called earlier. The success handler for this method is VoteSucceeded, when the vote is successful, we need to reset the voting buttons to be disabled and display the way the user voted, since we already have code that does this in CheckVote, we simply call CheckVote here and the form is reset as expected.

Registering the Script

I'll go over registering the client script in part two of this post tomorrow.