ASP.NET Core MVC: Comment Replies Not Working After Refactoring

I am working on an ASP.NET Core MVC project that involves posts and comments. Users can leave comments on posts, and they can also reply to other comments. The initial implementation was working (Check this commit), but after some refactoring, the reply functionality stopped working. Now, when I try to reply to a comment, the page just refreshes without hitting the controller action.

Previous Working Implementation:

Controller Action for Adding Comment:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddComment(Comment comment)
{
    var user = await _userManager.GetUserAsync(User);
    if (user != null)
    {
        comment.AuthorId = user.Id;
        comment.CreatedAt = DateTime.Now;
        _context.Comments.Add(comment);
        await _context.SaveChangesAsync();
    }
    return RedirectToAction(nameof(Details), new { id = comment.PostId });
}

Post Index View:

@using System.Security.Claims
@model IEnumerable<ArianNovinWeb.Models.Post>

@{
    ViewData["Title"] = "Posts";
}

<div class="container">
    <h1 class="mb-4">Posts</h1>

    <p>
        <a asp-action="Create" class="btn btn-primary">Create New Post</a>
    </p>

    <div class="row">
        @foreach (var post in Model)
        {
            <div class="col-md-6 mb-4">
                <div class="card">
                    @if (!string.IsNullOrEmpty(post.ImagePath))
                    {
                        <img src="@post.ImagePath" class="card-img-top" alt="Post Image" />
                    }
                    <div class="card-body">
                        <h5 class="card-title">@post.Title</h5>
                        <p class="card-text">@post.Description</p>
                        <p class="card-text"><small class="text-muted">Created by @post.Author?.UserName on @post.CreateDate.ToString("g")</small></p>

                        <h6>Comments</h6>
                        @if (post.Comments != null && post.Comments.Any())
                        {
                            @foreach (var comment in post.Comments.Where(c => c.ParentCommentId == null))
                            {
                                @await Html.PartialAsync("_CommentPartial", comment)
                            }
                        }
                        else
                        {
                            <p>No comments yet. Be the first to comment!</p>
                        }

                        <!-- Comment form -->
                        <form asp-action="AddComment" method="post" class="mt-3">
                            <input type="hidden" name="PostId" value="@post.PostId" />
                            <div class="mb-3">
                                <label for="Content" class="form-label">Comment:</label>
                                <textarea id="Content" name="Content" rows="3" class="form-control" required></textarea>
                            </div>
                            <button type="submit" class="btn btn-secondary">Add Comment</button>
                        </form>

                        <div class="mt-3 d-flex justify-content-between">
                            @if (User.Identity.IsAuthenticated && post.AuthorId == User.FindFirstValue(System.Security.Claims.ClaimTypes.NameIdentifier))
                            {
                                <div>
                                    <a asp-action="Edit" asp-route-id="@post.PostId" class="btn btn-outline-primary btn-sm">Edit</a>
                                    <a asp-action="Delete" asp-route-id="@post.PostId" class="btn btn-outline-danger btn-sm">Delete</a>
                                </div>
                            }
                            <a asp-action="Details" asp-route-id="@post.PostId" class="btn btn-outline-info btn-sm">Details</a>
                        </div>
                    </div>
                </div>
            </div>
        }
    </div>
</div>

Comment Partial View:

@model ArianNovinWeb.Models.Comment

<div class="card mb-2">
    <div class="card-body">
        <p class="card-text">@Model.Content</p>
        <p class="card-text">
            <small class="text-muted">
                Posted by @Model.Author?.UserName on @Model.CreatedAt.ToString("g")
            </small>
        </p>

        <!-- Reply form -->
        <form asp-action="AddComment" method="post" class="mt-2">
            <input type="hidden" name="PostId" value="@Model.PostId" />
            <input type="hidden" name="ParentCommentId" value="@Model.CommentId" />
            <div class="mb-2">
                <textarea name="Content" class="form-control" rows="2" placeholder="Reply..." required></textarea>
            </div>
            <button type="submit" class="btn btn-secondary btn-sm">Reply</button>
        </form>

        <!-- Render replies recursively -->
        @if (Model.Replies != null && Model.Replies.Any())
        {
            <div class="ml-4 mt-2">
                @foreach (var reply in Model.Replies)
                {
                    @await Html.PartialAsync("_CommentPartial", reply)
                }
            </div>
        }
    </div>
</div>

Current Non-Working Implementation:

Controller Action for Adding Comment:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddComment(int postId, string content, int? parentCommentId)
{
    if (!ModelState.IsValid)
    {
        TempData["ErrorMessage"] = "Failed to add comment. Please try again.";
        return RedirectToAction("Index", new { id = postId });
    }

    var user = await _userManager.GetUserAsync(User);
    if (user == null)
    {
        return Forbid();
    }

    var comment = new Comment
    {
        PostId = postId,
        Content = content,
        AuthorId = user.Id,
        CreatedAt = DateTime.Now,
        ParentCommentId = parentCommentId
    };

    _context.Comments.Add(comment);
    await _context.SaveChangesAsync();

    TempData["SuccessMessage"] = "Comment added successfully!";
    return RedirectToAction("Index", new { id = postId });
}

Post Index View:

@using System.Security.Claims
@model ArianNovinWeb.ViewModels.PostIndexViewModel

@{
    ViewData["Title"] = "Post Details";
}

<div class="container mt-4">
    @if (Model.ShowShareButton)
    {
        <div class="text-center mt-5">
            <h2>No Posts Available</h2>
            <p>Be the first to share a post!</p>
            <a asp-action="Create" class="btn btn-primary">Share Post</a>
        </div>
    }
    else
    {
        <div class="row">
            <div class="col-md-2 mt-10">
                @await Html.PartialAsync("_LatestItemsPartial", Model.LatestPosts)
            </div>
            <div class="col-md-6">
                <div class="d-flex justify-content-between align-items-center mb-3">
                    <div>
                        <a asp-action="Create" class="btn btn-primary">Share Post</a>
                    </div>
                    <div>
                        @if (Model.PostNavigation.PreviousPostId.HasValue)
                        {
                            <a asp-action="Index" asp-route-id="@Model.PostNavigation.PreviousPostId" class="btn btn-primary">Previous</a>
                        }
                        @if (Model.PostNavigation.NextPostId.HasValue)
                        {
                            <a asp-action="Index" asp-route-id="@Model.PostNavigation.NextPostId" class="btn btn-primary">Next</a>
                        }
                    </div>
                </div>
                <div class="card">
                    <h3 class="card-header">@Model.PostNavigation.Post.Title</h3>
                    <div class="card-body">
                    <h5 class="card-title">By: @Model.PostNavigation.Post.Author</h5>
                    <h6 class="card-subtitle text-muted">Posted at: @Model.PostNavigation.Post.CreateDate</h6>
                    </div>
                    @if (!string.IsNullOrEmpty(Model.PostNavigation.Post.ImagePath))
                    {
                        <img src="@Model.PostNavigation.Post.ImagePath" alt="Post Image" class="img-fluid" />
                    }
                    <div class="card-body">
                        <p class="card-text">@Model.PostNavigation.Post.Description</p>
                    </div>
                    <div class="mt-3 d-flex justify-content-between">
                        @if (User.Identity.IsAuthenticated && @Model.PostNavigation.Post.AuthorId == User.FindFirstValue(System.Security.Claims.ClaimTypes.NameIdentifier))
                        {
                            <div>
                                <a asp-action="Edit" asp-route-id="@Model.PostNavigation.Post.PostId" class="btn btn-outline-primary btn-sm">Edit</a>
                                <a asp-action="Delete" asp-route-id="@Model.PostNavigation.Post.PostId" class="btn btn-outline-danger btn-sm">Delete</a>
                            </div>
                        }
                        <a asp-action="Details" asp-route-id="@Model.PostNavigation.Post.PostId" class="btn btn-outline-info btn-sm">Details</a>
                    </div>
                </div>

                <!-- Comment form -->
                <div class="card mt-3 ">
                    <div class="card-body ">
                        <h3>Leave a Comment</h3>
                        <form asp-action="AddComment" method="post">
                            <input type="hidden" name="PostId" value="@Model.PostNavigation.Post.PostId" />
                            <div class="form-group">
                                <label for="Content">Comment:</label>
                                <textarea id="Content" name="Content" rows="4" required class="form-control"></textarea>
                            </div>
                            <button type="submit" class="btn btn-primary mt-2">Add Comment</button>
                        </form>
                    </div>
                </div>
            </div>

            <div class="col-md-4 mt-3">
                <div class="comment-section">
                    <h3>Comments</h3>
                    <!-- Display comments -->
                    @if (Model.PostNavigation.Post.Comments.Any())
                    {
                        @foreach (var comment in Model.PostNavigation.Post.Comments)
                        {
                            <div class="comment mb-3">
                                @await Html.PartialAsync("_CommentPartial", comment)
                            </div>
                        }
                    }
                    else
                    {
                        <p>No comments yet.</p>
                    }
                </div>
            </div>
        </div>
    }
</div>

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
    <script>
        $(document).ready(function () {
            var successMessage = '@TempData["SuccessMessage"]';
            if (successMessage) {
                toastr.success(successMessage);
            }
            var errorMessage = '@TempData["ErrorMessage"]';
            if (errorMessage) {
                toastr.error(errorMessage);
            }
        });
    </script>
}

Comment Partial View:

@model ArianNovinWeb.Models.Comment

<div class="card border-primary mb-3">
    <div class="card-body">
        <p class="card-header">
            @if (Model.Author.UserName != null)
            {
                <small class="text-black">
                    Post by @Model.Author.UserName at @Model.CreatedAt
                </small>
            }
            else
            {
                <small class="text-black">
                    Post by @Model.Author.Email at @Model.CreatedAt
                </small>
            }
        </p>
        <p class="card-text">@Model.Content</p>

        <!-- Reply form -->
        <form asp-action="AddReply" method="post">
            @Html.AntiForgeryToken()
            <input type="hidden" name="postId" value="@Model.PostId" />
            <input type="hidden" name="parentCommentId" value="@Model.CommentId" />
            <div class="mb-2">
                <textarea name="content" class="form-control" rows="2" placeholder="Reply..." required></textarea>
            </div>
            <button type="submit" class="btn btn-secondary btn-sm">Reply</button>
        </form>

        <!-- Render replies recursively -->
        @if (Model.Replies != null && Model.Replies.Any())
        {
            <div class="ml-4 mt-2">
                @foreach (var reply in Model.Replies)
                {
                    @await Html.PartialAsync("_CommentPartial", reply)
                }
            </div>
        }
    </div>
</div>

PostIndexViewModel:

using ArianNovinWeb.Models;
using ArianNovinWeb.ViewModels;

namespace ArianNovinWeb.ViewModels
{
    public class PostIndexViewModel
    {
        public List<Post> Posts { get; set; }
        public PostNavigationViewModel PostNavigation { get; set; }
        public LatestItemsVM LatestPosts { get; set; }
        public bool ShowShareButton { get; set; }
    }
}

Issue:
When I submit a reply, it refreshes the post index view and nothing happens. The action method AddComment is never hit, and I can’t figure out why. There are no errors in the browser console, and the form seems to be posting correctly.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật