0

I want to implement "like" button (only like, not dislike) in my project written on ASP.NET Core 2.1 version. This is discount classified site and want visitors to be able to like posts they want. Since I don't have any issue with namespace, I'll only provide action method in the controller from backend, which is as follows:

 [HttpPost]
 public async Task<IActionResult> AddLike(int Id)
        {
            AdminPostModel postModel = new AdminPostModel();
            postModel.Post = await _offerDbContext.Posts.SingleOrDefaultAsync(x => x.Id == Id);
            var UserIP = _accessor.HttpContext?.Connection?.RemoteIpAddress?.ToString();
            var Myagent = Request.Headers["User-Agent"].ToString().Substring(0, 40);
            string MyVisit = UserIP + " " + Myagent;
            postModel.Visitinfos = await _offerDbContext.Visitinfos.ToListAsync();
            Visitinfo visitinfo = new Visitinfo();
            visitinfo.PostNumber = Id;
            visitinfo.Deviceinfo = MyVisit;
           if(postModel.Visitinfos.Any(x => x.PostNumber == visitinfo.PostNumber && x.Deviceinfo == visitinfo.Deviceinfo))
            {
                ViewBag.Message = "Eyni elanı bir dəfədən çox bəyənə bilməzsiniz";
                return Json(postModel.Post.LikeCount);
            }
            else
            {
                _offerDbContext.Visitinfos.Add(visitinfo);
                 postModel.Post.LikeCount++;
                await _offerDbContext.SaveChangesAsync();
                return Json(postModel.Post.LikeCount);
            }
        }

Please, don't confuse yourself with user IP or user-agent details which is not related to my problem. I returned JSON with the result of number of likes (LikeCount) which is the property of Post model, and accessed it through view model in this action. Here is posts parts of cshtml view:

  @foreach (Post item in Model)
{
  <div class="postcontent">
                              <div class="row">
                                    <div class="col-lg-12 col-md-12">
                                        <div class="uppart">
                                            <h6>@item.Title</h6>
                                        </div>
                                        <div class="imgframe">
                                            @if (item.URL != null)
                                            {
                                                <a href="@item.URL" target="_blank"> <img class="postimg" src="~/images/@item.Image"></a>
                                            }
                                            else
                                            {
                                                <a asp-action="Detailed" asp-controller="Detailed" asp-route-id="@item.Id" target="_blank"><img class="postimg" src="~/images/@item.Image"></a>
                                            }
                                        </div>
                                        <div class="posttext">
                                            <p>
                                                @item.Description
                                            </p>
                                            <p class="formore">
                                               
                                                    <a href="@item.URL" target="_blank">ƏTRAFLI</a>
                                            </p>    
                                        </div>
                                        <div class="dates">
                                            <p class="postdate">Tarix: @item.CreatedDate.ToString("dd/MM/yyyy")</p>
                                            @if (item.ExpirationDate.ToString("dd/MM/yyyy") == "01.01.2021" || item.ExpirationDate.ToString("dd/MM/yyyy") == "01/01/2019")
                                            {
                                                <p class="expdate">Bitme tarix: Naməlum</p>
                                            }
                                            else
                                            {
                                                <p class="expdate">Bitme tarix: @item.ExpirationDate.ToString("dd/MM/yyyy") </p>
                                            }
                                            **<button onclick="IncreaseLike(@item.Id)">Like</button>
                                            <p class="like"></p>**
                                        </div>
                                    </div>
                                </div>

As you see, within button tag, I called IncreaseLike() function for Post Id, which is used in Javascript part like below:

@section Script{
    <script>
        function IncreaseLike(id) {
            $.ajax({
                url: "/Home/AddLike",
                type: "POST",
                data: { id: id },
            }).done(function (result) {
                $(".like").append(result);
            }
               )
            };
        
    </script>
}

The aim of using AJAX is to interrupt page loading after clicking on "like" button. But when running application, after clicking on "like" button it adds new 1 next to previous 1 instead of updating figure on its place. And it applies it for all posts of the page instead of only particular clicked one. Maybe it's because I append it to a class (.like), but I don't want to define different Id for each post in the page, how can I implement ajax so that it would append to only chosen post, and only one time by increasing like number, not to place new next to the number? There is no issue with database as it works without using ajax and using asp-action and asp-controller tag helpers, but this makes the page load in each click. Please, read my code carefully, and assist in finding issue which probably comes from JS part (AJAX).

2
  • 1
    append does exactly what you are seeing. It appends the new text after the current one. You should use text() or html(). Then why don't you want to set an individual id for each button? It is just like id='btn' + @item.id and it will be easy to set the individual text. Finally the fact the you see always 1 as LikeCount probably depends on the database code. Check it. Commented Jan 4 at 15:01
  • 1
    As an aside to the question, .Net Core 2.1 is very outdated now and has been out of support for well over 3 years. .Net9 is available to use, and .Net8 is the latest LTS version. You should really be using one of those, for security, if not performance alone. Commented Jan 4 at 15:07

2 Answers 2

3

Your jquery code should use .html() which replaces the HTML content of the target element.

@section Script{
    <script>
        function IncreaseLike(id) {
            $.ajax({
                url: "/Home/AddLike",
                type: "POST",
                data: { id: id },
            }).done(function (result) {
                $(".like").html(result);
            })
        };
    </script>
}

Since you don't want to add data-id for each post in the page, follow the steps below to replace the nearest post from the button you clicked.

  1. Replace your button element with;
<button onclick="IncreaseLike(@item.Id,this)">Like</button>
  1. Add the new parameter button to your function and use .parent() to replace the nearest .like.
@section Script{
    <script>
        function IncreaseLike(id, button) {
            $.ajax({
                url: "/Home/AddLike",
                type: "POST",
                data: { id: id },
            }).done(function (result) {
                $(button).parent().find(".like").html(result);
            })
        };
    </script>
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, it works by adding 1, but that result disappears after refreshing or re-entering the page. How can I make that result stay on the page to make another one see number of likes before they like the same post? One way may be to write @item.LikeCount directly from database, but it will not update new result if new visitor likes the particular post, he/she will only see new result after refresh. Would be happy if you can solve it completely.
I added @item.LikeCount to empty <p> in html, and it worked without need for refresh. Thank you Jerdine Sabio for your help and advice.
1

The issue is because append() is true to its name - it appends the new data to the existing content. To replace the content you can use html() instead.

However you can both fix the issue and make your code more succinct by using the load() method to make an AJAX request to the target endpoint and replace the content of the selected element with the response of that request:

function IncreaseLike(id) {
  $('.like').load('/Home/AddLike', { id: id });
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.