Search code examples
javascriptc#asp.net-corebootstrap-modalrazor-pages

Getting a 405 error when trying to call Delete Modal Confirmation action (Asp.Net Core 6 javascript)


I'm working on my first Asp.Net Core application, and am struggling with modals, Razor pages and route mapping are completely new things for me, and javascript is a pretty old thing for me. I'm trying to create a delete modal that can be used for any object (my test object is of type Employee). Maybe this isn't possible, I'm not sure. My modal displays fine, but when I click to call my DeletePOST method I get a 405 error. The URL in question returns as https://localhost:44313/Employee/DeletePOST/1 (when the employee with id = 1 is selected). The "warning" message that I get in the console is (index):6789 crbug/1173575, non-JS module files deprecated.(anonymous) @ (index):6789.

Here is the applicable code from View.Employee.Index

<tbody>
    @foreach (var employee in Model)
    {
        <tr id="[email protected]">
            <td>@employee.Name</td>
            <td>@employee.Phone</td>
            <td>@employee.Email</td>
            <td>@employee.Address</td>
            <td>@employee.Role</td>
            <td>@employee.Availability</td>
                    
            <td class="w-100 btn-group" role="group">
                <a asp-controller="Employee" asp-action="Edit" asp-route-id="@employee.Id"
                   class="btn btn-primary mx-2"> <i class="bi bi-pencil-square"></i> Edit</a>
                        
                <!--delete modal confirmation button-->
                <a class="btn btn-danger delete" id="#delete" data-id="@employee.Id" 
                   data-url ="@Url.Action("DeletePOST","Employee")/"
                   data-body-message= "Are you sure you want to delete this employee?">
                   <i class="bi bi-trash"></i> Delete</a>
            </td>
                    
        </tr>
    }
</tbody>

Code from wwwroot.js.delete.js

$((function () {
    var target;
    var pathToDelete;
    var id;

    $('body').append(`
                    <div class="modal fade" id="deleteModal" tabindex="-1" role="dialog"
                         aria-labelledby="myModalLabel">
                        <div class="modal-dialog" role="document">
                            <div class="modal-content">
                                <div class="modal-header">
                                    <button type="button" class="close" data-bs-dismiss="modal" 
                                      aria-label="Close"><span aria-hidden="true">&times;</span> </button>
                                    <h4 class="modal-title" id="myModalLabel">Warning</h4>
                                </div>
                                <div class="modal-body delete-modal-body">
                                </div>
                                <div class="modal-footer">
                                    <button type="button" class="btn btn-default" data-dismiss="modal" 
                                        id="cancel-delete">Cancel</button>
                                    <button type="submit" class="btn btn-danger" 
                                        id="confirm-delete">Delete</button>
                                </div>
                            </div>
                        </div>
                    </div>`);
    
    //Delete Action
    $(".delete").on('click', (e) => {
        e.preventDefault();
        target = e.target;
        id = $(target).data('id');
        pathToDelete = $(target).data('url');
        
        var bodyMessage = $(target).data('body-message');
        pathToDelete = pathToDelete + id;
        $(".delete-modal-body").text(bodyMessage);
        $("#deleteModal").modal('show');
    });

    $("#confirm-delete").on('click', () => {
        window.location.href = pathToDelete;  //suspect issue
    });
}()));

Code from Controllers.EmployeeController.cs

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult DeletePOST(int? id)
{
    var selectedEmployee = _db.Employees.Find(id);
    if (selectedEmployee == null)
    {
        return NotFound();
    }
    _db.Employees.Remove(selectedEmployee);
    _db.SaveChanges();
    return RedirectToAction("Index");   //suspect issue
}
```

Solution

  • If you want to call DeletePOST in js,you can try to use ajax,since you need to add AntiForgeryToken to the request,you also need to add @Html.AntiForgoryTokento your view:

    view:

    <tbody>
        @foreach (var employee in Model)
        {
            <tr id="[email protected]">
                <td>@employee.Name</td>
                <td>@employee.Phone</td>
                <td>@employee.Email</td>
                <td>@employee.Address</td>
                <td>@employee.Role</td>
                <td>@employee.Availability</td>
                        
                <td class="w-100 btn-group" role="group">
                    <a asp-controller="Employee" asp-action="Edit" asp-route-id="@employee.Id"
                       class="btn btn-primary mx-2"> <i class="bi bi-pencil-square"></i> Edit</a>
                            
                    <!--delete modal confirmation button-->
                    <a class="btn btn-danger delete" id="#delete" data-id="@employee.Id" 
                       data-url ="@Url.Action("DeletePOST","Employee")/"
                       data-body-message= "Are you sure you want to delete this employee?">
                       <i class="bi bi-trash"></i> Delete</a>
                </td>
                        
            </tr>
        }
    </tbody>
    @Html.AntiForgoryToken
    

    js:

    $("#confirm-delete").on('click', () => {
            $.ajax({
                    type: "POST",
                    url: pathToDelete,
                    headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
                }).done(function (result) {
                    //redirect to Index here
                    window.location.href="Index";
                });
        });
    

    Or you can remove the following code in Controller:

    [HttpPost]
    [ValidateAntiForgeryToken]