Home > Blockchain >  Problem with deleting data from jQuery Datatable and database in ASP.NET Core project
Problem with deleting data from jQuery Datatable and database in ASP.NET Core project

Time:03-07

I am using jQuery Datatable to visualize the information for the payments done by each user. I have created both "Edit" and "Delete" buttons in the table. However, the delete button is not working - I think I'm not triggering the Action method of my PaymentsController properly. My paymentsTable.js has the following script:

$(document).ready(function () {
    $("#paymentsTable").DataTable({
        "processing": true,
        "responsive": true,
        "serverSide": true,
        "filter": true,
        "language": {
            "lengthMenu": "Показване на _MENU_ плащания на страница",
            "zeroRecords": "Няма открити съвпадения",
            "info": "Открити са _PAGE_ от _PAGES_ плащания",
            "infoEmpty": "Няма плащания",
            "infoFiltered": "(претърсено от _MAX_ плащания общо)",
        },
        "ajax": {
            "url": "/Users/GetUserPayments",
            "beforeSend": function (xhr) {
                xhr.setRequestHeader("XSRF-TOKEN",
                    $('input:hidden[name="__RequestVerificationToken"]').val());
            },
            "type": "POST",
            "datatype": "json"
        },
        "columnDefs": [
            {
                "targets": [0],
                "visible": false,
                "searchable": false,
                "className": "dt-body-center",
            },
            {
                "targets": 1,
                "render": function (data, type, row) {
                    return (data)
                        ? moment(data, "YYYY-MM-DD").format("DD/MM/YYYY")
                        : null;
                }
            },
        ],
        "columns": [
            { "data": "id", "name": "Id", "autoWidth": true },
            { "data": "dateOfPayment", "name": "DateOfPayment", "autoWidth": true },
            { "data": "description", "name": "Description", "autoWidth": true },
            { "data": "amount", "name": "Amount", "autoWidth": true },
            {
                "render": function (data, type, full, meta) {
                    return "<a class='btn btn-secondary border border-white' onclick=GoToEditView('"   full.id   "'); >Edit</a> <a class='btn btn-secondary border border-white' onclick=DeleteData('"   full.id   "'); >Delete</a>";
                },
            },
        ]
    });
});

function GoToEditView(id) {
    window.location.href = 'https://localhost:44319/Payments/Edit/'   id;
}

function DeleteData(id) {
    if (confirm("Наистина ли желаете да изтриете данните за това разплащане?")) {
        Delete(id);
    } else {
        return false;
    }
}

function Delete(id) {
    $.ajax({
        type: 'POST',
        url: "/Payments/Delete",
        data: { id: id },
        success: function (r) {
            window.location.reload();
        }
    });
}
My controller has the following code:

[Authorize(Roles = GlobalConstants.AdministratorRoleName)]
public class PaymentsController : Controller
{
    private readonly IPaymentsService paymentsService;

    public PaymentsController(
        IPaymentsService paymentsService)
    {
        this.paymentsService = paymentsService;
    }

    public IActionResult Create(string id)
    {
        return this.View();
    }

    [HttpPost]
    public async Task<IActionResult> Create(string id, PaymentInputModel input)
    {
        if (!this.ModelState.IsValid)
        {
            return this.View(input);
        }

        try
        {
            await this.paymentsService.CreateAsync(input, id);
        }
        catch (Exception e)
        {
            this.ModelState.AddModelError(string.Empty, e.Message);
            return this.View(input);
        }

        return this.Redirect("/Users/ById/"   id);
    }

    [HttpPost]
    public async Task<IActionResult> Delete(string id)
    {
        await this.paymentsService.DeleteAsync(id);

        var userId = this.HttpContext.Session.GetString("userId");

        return this.RedirectToAction("/Users/ById/"   userId);
    }

    public IActionResult Edit(string id)
    {
        var inputModel = this.paymentsService.GetById<PaymentInputModel>(id);

        return this.View(inputModel);
    }

    [HttpPost]
    public async Task<IActionResult> Edit(string id, PaymentInputModel input)
    {
        if (!this.ModelState.IsValid)
        {
            return this.View(input);
        }

        await this.paymentsService.UpdateAsync(id, input);

        id = input.UserId;

        return this.RedirectToAction(nameof(UsersController.ById), "Users", new { id });
    }
}

And this is my ById.cshtml file (the profile view of a user), which is triggered by the UsersController. Here is where I want my paymentsTable to be visualized.

@model ChessBurgas64.Web.ViewModels.Users.UserProfileViewModel
@using ChessBurgas64.Common
@using ChessBurgas64.Data.Models.Enums

@{
    this.ViewData["Title"] = String.Concat(Model.FirstName, " ", Model.MiddleName, " ", Model.LastName);
}

<link href="~/lib/datatables.net-bs5/dataTables.bootstrap5.min.css" rel="stylesheet" />

<h1 >@GlobalConstants.Profile</h1>

<div >
    <h3 >@this.ViewData["Title"]</h3>
</div>


<div >
    <div >
        <h4 >@GlobalConstants.PersonalData</h4>
        <hr  />

        <div >
            <p>@GlobalConstants.Gender: <i ></i> @Model.Gender</p>
            <hr  />
            <p>@GlobalConstants.BirthDate: <i ></i> @Model.BirthDate.ToShortDateString()</p>
            <hr  />

            @if (Model.Member != null)
            {
                <p>@GlobalConstants.Address: <i ></i> @Model.Member.Address</p>
                <hr  />
                <p>@GlobalConstants.School: <i ></i> @Model.Member.School</p>
                <hr  />
            }

            <p>@GlobalConstants.ClubStatus: <i ></i> @Model.ClubStatus</p>
            <hr  />
        </div>
    </div>

    <div >
        <h4 >@GlobalConstants.ClubData</h4>
        <hr  />

        <div >
            @if (Model.Member != null)
            {
                <p>@GlobalConstants.ClubRating: <i ></i> @Model.Member.ClubRating</p>
                <hr  />
                <p>@GlobalConstants.DateOfJoiningTheClub: <i ></i> @Model.Member.DateOfJoiningTheClub.ToShortDateString()</p>
                <hr  />

                @if (Model.Member.Group != null)
                {
                    <p>@GlobalConstants.Group: <i ></i> @Model.Member.Group.Name</p>
                    <hr  />
                    <p>@GlobalConstants.DateOfJoiningCurrentGroup: <i ></i> @Model.Member.DateOfJoiningCurrentGroup.ToShortDateString()</p>
                    <hr  />
                }
                else
                {
                    <p>@GlobalConstants.Group: <i ></i> @GlobalConstants.None</p>
                    <hr  />
                }

                <p>@GlobalConstants.LastAttendance: <i ></i> @Model.Member.DateOfLastAttendance.ToShortDateString()</p>
                <hr  />
            }
            else
            {
                @GlobalConstants.MemberStillNotAddedToTheSystem
            }
        </div>
    </div>

    <div >
        @if (Model.ClubStatus == ClubStatus.Треньор.ToString())
        {
            <a  asp-action="EditTrainerInfo" asp-route-id="@Model.Id">@GlobalConstants.Edit</a>
        }
        else
        {
            <a  asp-action="EditMemberInfo" asp-route-id="@Model.Id">@GlobalConstants.Edit</a>
        }
    </div>

    <div >
        <h4 >@GlobalConstants.Payments</h4>
        <hr  />
        <div  style="width:100%; margin:0 auto;">
            <table id="paymentsTable"  width="100%" cellspacing="0">
                <thead >
                    <tr>
                        <th >Id</th>
                        <th >@GlobalConstants.DateOfPayment</th>
                        <th >@GlobalConstants.PaidFor</th>
                        <th >@GlobalConstants.PaidAmount</th>
                        <th >@GlobalConstants.Actions</th>
                    </tr>
                </thead>
            </table>
        </div>
        <a  asp-area="" asp-controller="Payments" asp-action="Create" asp-route-id="@Model.Id">@GlobalConstants.AddPayment</a>
    </div>
</div>

@Html.AntiForgeryToken()

@section Scripts
{
    <script src="~/lib/datatables.net/jquery.dataTables.min.js"></script>
    <script src="~/lib/datatables.net-bs5/dataTables.bootstrap5.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.4/moment.min.js"></script>
    <script src=" //cdn.datatables.net/plug-ins/1.10.11/sorting/datetime-moment.js"></script>
    <script src="~/js/paymentsTable.js"></script>
}

While I was debugging I noticed that after clicking the "Delete" button the "Delete" action method in my PaymentsController is not triggered at all and there is an error with status code 400. I am not sure how exactly to call this method, since I have no "DeleteView". I am new to this so I am probably missing something important. I tried different solutions and none of them work. Please, help!

CodePudding user response:

Add Token, try code as blelow to change your delete ajax:

function Delete(id) {
    $.ajax({
        type: 'POST',
        url: "/Payments/Delete",
        "beforeSend": function (xhr) {
                xhr.setRequestHeader("XSRF-TOKEN",
                    $('input:hidden[name="__RequestVerificationToken"]').val());
            },
        data: { id: id },
        success: function (r) {
            window.location.reload();
        }
    });
}
  • Related