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();
}
});
}