views:

106

answers:

3

So I have a simple voting feature on my asp.net mvc page. My index page is loaded with all the posts in the database. A user can vote yes or no as to whether they liked the post or not via links within each post. So in my database I have a table called posts and there are two fields in that table named vote_yes and vote_no that track the vote counts.

My vote action has no view because it is a JSONResult method, but my view for the index action looks like this:

 <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<INDA.Models.Post>>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Welcome
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <% foreach (var item in Model) { %>

        <div class="post">
         <div class="postText">
          <%= Html.Encode(item.message) %>
      </div>
      <div class="postInfo">
       <span class="timestamp left">
           Posted by <em><%= Html.Encode(item.author)%></em> on 
           <%= Html.Encode(String.Format("{0:g}", item.date)) %>
       </span> 
       <span class="voting right">
        Comments<em>
               <%= Html.ActionLink(
                                "Liked This (" + Html.Encode(item.vote_yes) + ")",
                                "Vote",
                                new { id = item.post_id, vote = "yes" },
                                new { @class = "vote_yes" } )%>
           </em> - 
           <em>
               <%= Html.ActionLink(
                                "Hated It (" + Html.Encode(item.vote_no) + ")",
                                "Vote",
                                new { id = item.post_id, vote = "no" },
                                new { @class = "vote_no" } )%>
           </em>
       </span>
       <div class="clear"></div>
      </div>  
     </div>

    <% } %>

</asp:Content>

Right now I'm only testing voting yes, so the jQuery in my master page looks like this:

$(document).ready(function() {
                $(".vote_yes").click(function() {
                    var currLink = $(this);
                    var action = currLink.attr("href");
                    $.getJSON(action, null, function(data) {
                        currLink.html("Liked This (" + data.vote_yes + ")");
                    });
                    return false;
                });
            });

And my PostsController with index and vote actions looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using INDA.Models;

namespace INDA.Controllers
{
    public class PostsController : Controller
    {
        INDARepository INDARepository = new INDARepository();

        // action methods
        [OutputCache(Location = OutputCacheLocation.None)]
        public ActionResult Index()
        {
            var posts = INDARepository.GetAllPosts().ToList();
            return View(posts);
        }

        [OutputCache(Location=OutputCacheLocation.None)]
        public JsonResult Vote(int id, string vote)
        {
            Post p = INDARepository.GetPost(id);
            if (vote == "yes")
            {
                p.vote_yes++;
            }
            else if (vote == "no")
            {
                p.vote_no++;
            }

            INDARepository.Save();

            return Json(p);
        }

    }
}

Now here's the problem. When I click the "Liked This (X)" link to vote yes in each post, it will go through the AJAX call and update the count in the database fine. However, the link in the first post will never update to reflect the new count of votes in the database, aka it should look like "Liked This (X + 1)" but remains "Liked This (X)". The strange part is that in all of the other posts, the links update fine. It's just the first post that never works. Can anyone help? I tried adding the no caching aspect, but to no avail.

Thanks and sorry this is so long, Ryan

A: 

Use Firbug and set a Breakpoint at currLink.html()

In the watch window enter currLink.html('test') and see what happens.

Then have a look at data.vote_yes in the watch window. I guess you will see the problem then.

Malcolm Frexner
A: 

Also with firebug you can see what returned from your server. It can be very useful

Also try to rewrite code as currLink.html("Request succeed") and click on "yes" for first post. If there is no server-side error then message will be changed.

But it looks like server side error while request for me, like your handler is never called. Also in Firebug try to set breakpoint on line with currLink.html.

Trickster
A: 

As far as I can tell there are 3 things which are possibly going wrong here.

  1. Put a breakpoint on the server where you return the post to make sure that you are returning an updated post
  2. Make sure the Json is working correctly - change the line that says currLink.html("Liked This (" + data.vote_yes + ")"); to something like currLink.html("bob") and do an alert(data.vote_yes)
  3. Make sure currLink is pointing to the correct DOM element either by using Firebug as suggested or doing a simple alert again.
Jaco Pretorius
Thanks for everyone's comments. It looks like the server code is sending back the updated post and I am updating the correct link, but there seems to be a problem with the JSON. Still looking into it right now.
ryanulit
Okay I've got it working now. I just made another variable handle the new number of votes and sent that via a new object declared in my return statement in the controller. I think the issue was with trying to access the properties of p in the callback. .NET might change the names to something unrecognizable when the page is served.
ryanulit