Search code examples
c#asp.netvoting-systemupdown

using cookies in up/down voting system


I want to build Up/down voting system for several articles retrieved from database, but i want to add cookie for each article to limit number of votes so cookie will expires in one day, but i don't know where to add the appropriate code.

more details:

<script>
    function vote(id, value) { // function vote with 2 arguments: article ID and value (+1 or -1) depending if you clicked on the arrow up or down
        var dataFields = { 'id': id, 'value': value }; // We pass the 2 arguments
        $.ajax({ // Ajax
            type: "POST",
            dataType: "text",//This for indicate that you'r expecting a text response from server
            url: "WebService.asmx/updateVotes",
            data: dataFields,
            timeout: 3000,

            success: function (dataBack) {
                if(
                    $('#number' + id).html(dataBack);// div "number" with the new number
                    $('#arrow_up' + id).html('<div class="arrow_up_voted"></div>'); // We replace the clickable "arrow up" by the not clickable one
                    $('#arrow_down' + id).html('<div class="arrow_down_voted"></div>'); // We replace the clickable "arrow down" by the not clickable one
                    $('#message' + id).html('<div id="alertFadeOut' + id + '" style="color: green">Thank you for voting</div>'); // Diplay message with a fadeout
                    $('#alertFadeOut' + id).fadeOut(1100, function () {
                        $('#alertFadeOut' + id).text('');
                    });
                },


            error: function () {
                $('#number' + id).text('Problem!');
            }
        });
    }


</script>

the above code is a script calling ajax method to increase number of votes per one every time user click on the up arrow and decrease conversely.

    public string updateVotes(string id,int value)
{

    System.Threading.Thread.Sleep(500); // delay for 2.5 seconds Network latency

   post p = db.posts.Find(int.Parse(id));
    // assign new values
   p.totalVotes += value;
    db.Entry(p).State = System.Data.EntityState.Modified;
    db.SaveChanges();

    string dataBack =p.totalVotes.ToString();
    return dataBack;
}

This is the webmethod.

Now i tried to think loudly and i code the following function to ewxamine if the cookie is null or not.

 public bool enableVoting()
{

    HttpCookie cookie = Request.Cookies["enableVote"];

    if (Request.Cookies["enableVote"] != null)
    {
       return true;

    }

    else
    {

      return false;
    }


}

i know it's wrong but at least i tried.

also where to add a for each loop to add cookie whenever user vote for article.?

   foreach(post p in db.posts){
        HttpCookie cookie = new HttpCookie("enableVote"+p.ID);
        cookie.Value = "article:"+p.ID;
        cookie.Expires = DateTime.Now.AddDays(1);
        Response.Cookies.Add(cookie);
    }

Solution

  • A suggestion. Don't use cookies for this. They are easily manipulated. Clear browser history and you can vote again.. and again.. and again.

    Instead, create a Vote table in your database and add a record with the ip of the voter and the id of the post they voted for along with a timestamp.

    This way you can easily count the votes and when someone votes you do a quick check on how long ago that IP last voted for that article (or any article).

    Also with a vote table in your database you can easily catch bots that are up or downvoting everything, and limit the number of votes a single ip can make on any article (no more than 1 or two votes every few minutes maybe).

    If your worried about multiple people behind the same IP not being able to vote you can include the browser name and only count unique ip and browser version as a vote. This is fairly unique. It can also be manipulated but its a little bit harder for the normal user.

    Update: I use this code for the purpose of getting a somewhat unique key in one of my MVC projects. The user can switch browsers and vote again, but it takes a bit of effort and its more of a pain than just clearing browser history.

    I combine the IP, browser, and Country into a string and use that as a vote key.

    public class UserInfo
    {
        public String ip { get; private set; }
        public String browser { get; private set; }
        public String country { get; private set; }
    
        public UserInfo(HttpRequestBase Request)
        {
            ip = Request.UserHostAddress;
            browser = Request.Browser.Platform + " " + Request.Browser.Type + "/" + Request.Browser.Id + " " + Request.Browser.Version;
            country = "";
    
            if (Request.UserLanguages.Length > 0)
                country += " - " + Request.UserLanguages.ElementAt(0);
        }
    }
    

    I'm using this system here: http://filepublicator.com/ to check if the user has any previously uploaded files (try to upload something and close browser and go there again, it will be in the list).