Creating a Content RaterBy Scott Mitchell
If you ever read an article on Microsoft's MSDN Web site, such as my article An Extensive Examination of User Controls, you'll notice that at the bottom of the article there's an interface for the reader to rate the content. (See the screenshot to the right.) Specifically, the user can rate the quality of the article on a scale from 1 to 9, with 1 being Poor, and 9 being Outstanding. In addition to affixing a numerical rating of the article, the reader can also provide optional comments in a textbox. Also included is a graph showing how other readers have rated the article. (CoDe Magazine's Web site uses a similar content rating system.)
The other day I thought it would be neat to add such functionality to my blog, ScottOnWriting.NET. Namely, I wanted to allow users to rate each blog entry, so that I could get a better idea of what content my visitors found most compelling. Another benefit of allowing users to rank content, is that after sufficient data has been collected you can provide users with a list of "most popular" content items. In this article I will walk you through the steps I took to create the content rater used on my blog. You are more than welcome to take my code and apply it to your ASP.NET Web site, or to extend it as needed.
First Things First: The Data Model
Each time a user rates a content item, the rating - along with any comments - are stored in a database (specifically, a Microsoft SQL Server 2000 database). I opted to store the ratings and comments in a database (as opposed to an XML file, for example), for one main reason: extracting metrics on the data is a cinch when using SQL. For example, a simple, single SQL query can be used to quickly determine the average rating for a particular content item. A more involved query could be used to determine what authors wrote the highest rated content, or what days of the week the least popular items were published.
To store the ratings for my blog's entries, I created a single table,
blog_Ratings, where each row in this
table would correspond to one rating from a user. The
blog_Ratings table has the following structure:
Rating field contains the numeric rating the user assigned to the content item, while
Comments stores the comments provided (if any).
ContentID is a foreign key that relates the
rating back to a particular content item. (For my blog I use the .Text blog engine,
which stores each blog entry as a row in a table called
blog_Content. This foreign-key ties a rating to
the particular blog entry being rated.) Finally, the
DateAdded field specifies the date/time the rating
was made (with a default value of
Creating the User Interface
With the data model complete, my next step was to create the user interface for rating a content item. Rather than display a ranking of 1 to 9 like MSDN does, I decided to simplify my design and only allow for a rating from 1 to 5 instead. I started by creating a new User Control in my ASP.NET Web application, and crafted a nearly identical interface to MSDN's content rater. The screenshot below shows my User Control in Visual Studio .NET and in action on my blog (you can download the User Control at the end of this article).
The User Control is contained within an HTML
<table>, dividing the interface into two halves: a left half,
which displays the rating interface; and a right-half, which displays the average rating and a graph depicting the rating history.
The left-half contains two Panel Web controls. The first Panel,
pnlCastVote, contains the HTML markup and
Web controls for rating a content item. The second Panel,
pnlVoteCast, contains just a message thanking the
user for rating the content. If a particular user has not rated a particular content item, they are shown the
Panel. If, however, they have already rated the content item, they are shown the
pnlVoteCast Panel. (Cookies
are used to remember what content items the user has rated.)
Specifying the Content Being Rated and Collecting the User's Rating
The User Control code-behind class contains a
ContentIDproperty that indicates the ID of the content being rated. That is, to use the content rater in an ASP.NET Web page, you'd include the User Control and then in the ASP.NET Web page's code-behind class you'd set the User Control's
ContentIDproperty to current content item's ID value. It is essential that this property be set in the ASP.NET Web page (such as in the
Page_Loadevent handler), because the User Control must know what content item it is rating.
To rate a content item, the user selects one of the radio buttons and clicks the Rate Content button. This causes a postback
and runs an event handler wired up to the Rate Content button's
Click event. The event handler code
checks to determine what radio button was selected, marks the user as having voted for the content item, and then
blog_AddRating stored procedure, passing in the user's rating, comments, and the ID for the content
being rated. (The
blog_AddRating stored procedure simply does an
Remembering If a User Has Rated a Content Item
Since we don't want one user to be able to rate a single content item dozens of times, after a user has rated a content item they are shown a message thanking them for their rating, as opposed to seeing the rating interface. For further protection, a cookie is used to record what content items the user has rated. If the user comes to a content item they've already rated, rather than seeing the rating interface, they are shown a message thanking them for their rating.
Cookies are by no means a fail-safe method to ensure that each visitor only rates a content item once. For one thing, users can configure their browsers to not accept cookies. Also, a cookie is specific to a Web browser, so a single person could use different browsers, or different computers, and record their rating more than once. The point is, the content rater I created by no means guarantees the validity of the ratings. If you want to be certain that there is only one rating per user, then you'd need to have a database of user accounts, and tie a rating to a particular user.
For the content rater I created, I created a Boolean
HasVoted property in the User Control code-behind class that
can be used to determine if a user has already voted on a particular content item or not. The property's
accessor checks to see if a cookie is in place, indicating that the user has rated this content item. The
accessor adds the appropriate cookie. The code for the
HasVoted property is shown below:
Note that the
HasVoted property checks a cookie called
sowBlog's value titled
ContentID-ID, where ID is the ID of the content item specified by the ASP.NET Web page
containing this User Control. (This property helps illustrate the importance of having the ASP.NET Web page
specify the User Control's
ContentID property; the
ContentID specifies what
cookie value to search for.)
Wrapping Up: Showing the Voting Statistics
The final piece of the puzzle is having the right-half of the rating interface display the total number of people who have rated the content, along with a graph showing the vote breakdown. This is accomplished in the
DisplayRateScreen()method in the User Control, and is called from the User Control's
blog_GetRatingInfostored procedure to get the information on how many votes for each rating there were, along with the average rating and how many total ratings have been made. This stored procedure expects a
ContentIDinput parameter, specifying the content item for which to generate the stats, and has the following syntax:
(The above stored procedure was provided by Richard Deeming...)
As you can see, the stored procedure returns one row with seven columns. The columns
Rating5Count return the number of 1 through 5 ratings the content item received.
returns the average rating, while
RatingCount returns the total number of ratings recorded for this
The graph depicting the rating breakdown is generated with an HTML
<table>, which one column for each
of the five possible ratings. Each column in the graph contains a single image, (
bcImage.gif), which is
stretched to a height proportional to the number of ratings received. For example, if there are twice as many 5 ratings
for a content item than there are 4 ratings, the 5 rating column height will be twice that of the 4 column height.
The specific proportion is computed as the number of votes for that rating, divided by the maximum number of votes
for any rating, multiplied by 50 (to scale the maximum height to 50 pixels).
|Learn About Adding Additional Features (April 30, 2004)...|
|On April 30, 2004, I authored a follow-up article: Improving the Content Rater. The newer article examines how to add two features to the content rater: a means to show users the highest rated items, and a page that shows all ratings and comments made, grouped by content item. Read on to learn more!|
In this article we looked at a simple User Control to allow users to rate content on your Web site. The rating User Control allows users to give a rating between 1 and 5, and displays an average rating along with a graph showing the rating history for the content item. The User Control employs cookies to remember whether or not a particular user has already rated this content item. While this method can easily be abused by a savvy user to rate a single content item more than once, it was chosen because of ease of implementation and the fact that the content rating system need not be infallible.
Once you have implemented this content rater on your site, you can add all sorts of other interesting features. For example, you could have a page that listed the 10 most popular content items. You might also find it useful to build an administrative Web page that listed the ratings for each content item, along with their comments, to give site editors a quick pulse on their readers' preferences. If you think of any other nifty way to extend this functionality, be sure to let me know!