0

I can't see why this code is not working. On clicking any Delete link in the table rows, I want to execute the OnPostDeleteAsync method, and it's not executing anything. The sweetalert2 pops up, I click Yes and nothing. No console error. I'm debugging with a break point on the OnPostDeleteAsync method and it's not getting hit. I've done similar in other pages that work and compared. I don't get it, maybe it's something simple I'm missing?

I temporarily commented out part of the javascript until I figure out why I'm not getting to the OnPostDeleteAsync method.

/Surveys/Index.cshtml

@page
@model Admin.Web.Pages.Surveys.IndexModel

@{
    ViewData["Title"] = "Surveys";
    Layout = "~/Pages/Shared/_Layout.cshtml";
}

@Html.AntiForgeryToken()

<h3>Surveys</h3>

<table class="table">
    <thead>
        <tr>
            <th>@Html.DisplayNameFor(model => model.Surveys[0].CuSurveyId)</th>
            <th>@Html.DisplayNameFor(model => model.Surveys[0].Name)</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @for (int i = 0; i < Model.Surveys.Count; i++)
        {
            var survey = Model.Surveys[i];
            <tr>
                <td>@Html.DisplayFor(model => survey.CuSurveyId)</td>
                <td>@Html.DisplayFor(model => survey.Name)</td>
                <td class="align-right">
                    @if (!Model.LineItems.Any(li => li.CuSurveyId == survey.CuSurveyId))
                    {
                        <a href="#" class="delete-survey" data-id="@Model.Surveys[i].Id">Delete</a>
                    }
                </td>
            </tr>
        }
    </tbody>
</table>

<hr />

<h4>Add a New Survey</h4>

<div class="row">
    <div class="col-md-4">
        <form method="post">
            <input type="hidden" asp-for="CrmClientId" />
            <div class="form-group">
                @Html.LabelFor(model => model.NewSurvey.CuSurveyId, new { @class = "control-label" })
                @Html.EditorFor(model => model.NewSurvey.CuSurveyId, new { htmlAttributes = new { @class = "form-control", @id = "cuSurveyIdInput" } })
            </div>
            <div class="form-group">
                @Html.LabelFor(model => model.NewSurvey.Name, new { @class = "control-label" })
                <div style="display: flex; align-items: center;">
                    @Html.EditorFor(model => model.NewSurvey.Name, new { htmlAttributes = new { @class = "form-control", @id = "nameInput" } })
                    <button type="button" id="copyButton" class="btn btn-secondary" title="Fill"><i class="fa-solid fa-arrow-right-to-bracket fa-flip-horizontal"></i></button>
                </div>
            </div>
            <div class="form-group">
                <button type="submit" class="btn btn-outline-primary" asp-page-handler="AddSurvey"><i class="fa-regular fa-floppy-disk"></i> Add Survey</button>
            </div>
        </form>
    </div>
</div>

@section Scripts {
    <script>
        document.getElementById('copyButton').addEventListener('click', function () {
            const cuSurveyIdInput = document.getElementById('cuSurveyIdInput');
            const nameInput = document.getElementById('nameInput');

            nameInput.value = cuSurveyIdInput.value;
        });

        document.addEventListener('DOMContentLoaded', function () {
            const token = document.querySelector('input[name="__RequestVerificationToken"]').value;
            const deleteLinks = document.querySelectorAll('.delete-survey');

            deleteLinks.forEach(link => {
                link.addEventListener('click', function (e) {
                    e.preventDefault();
                    const surveyId = this.getAttribute('data-id');
                    Swal.fire({
                        title: 'Are you sure?',
                        text: "You won't be able to revert this!",
                        icon: 'warning',
                        showCancelButton: true,
                        confirmButtonText: 'Yes, delete it!',
                        cancelButtonText: 'Cancel'
                    }).then((result) => {
                        if (result.isConfirmed) {
                            fetch(`./Index?handler=Delete&id=${surveyId}`, {
                                method: 'POST',
                                headers: {
                                    'RequestVerificationToken': token,
                                    'Content-Type': 'application/x-www-form-urlencoded'
                                }
                            //})
                            //    .then(response => response.json())
                            //    .then(data => {
                            //        if (data.success) {
                            //            Swal.fire(
                            //                'Deleted!',
                            //                'The survey has been deleted.',
                            //                'success'
                            //            );
                            //            // Refresh the page or remove the survey row from the DOM
                            //        }
                                });
                        }
                    });
                });
            });
        });
    </script>
}

/Surveys/Index.cshtml.cs

using Admin.Data.Contexts;
using Admin.Data.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;

namespace Admin.Web.Pages.Surveys;

public class IndexModel : PageModel
{
    private readonly AppDbContext _context;

    public IndexModel(AppDbContext context)
    {
        _context = context;
    }

    [BindProperty]
    public Guid? CrmClientId { get; set; }

    public IList<Survey> Surveys { get; set; }

    public IList<LineItem> LineItems { get; set; }


    [BindProperty]
    public Survey NewSurvey { get; set; } = new Survey();

    public async Task<IActionResult> OnGetAsync(Guid? id)
    {
        CrmClientId = id;

        if (CrmClientId == null)
        {
            return NotFound();
        }

        LineItems = await _context.CrmLineItems.ToListAsync();

        Surveys = await _context.CrmSurveys
                        .Where(s => s.ClientId == CrmClientId)
                        .ToListAsync();
        return Page();
    }

    public async Task<IActionResult> OnPostAddSurveyAsync()
    {
        if (CrmClientId == null)
        {
            return NotFound();
        }

        NewSurvey.ClientId = CrmClientId.Value;

        _context.CrmSurveys.Add(NewSurvey);
        await _context.SaveChangesAsync();

        return RedirectToPage(new { id = CrmClientId });
    }

    public async Task<IActionResult> OnPostDeleteAsync(Guid id)
    {
        Console.WriteLine("Entered OnPostDeleteAsync");

        var survey = await _context.CrmSurveys.FindAsync(id);

        if (survey != null)
        {
            // Check if the survey is being used in LineItems
            bool isUsed = await _context.CrmLineItems.AnyAsync(li => li.CuSurveyId == survey.CuSurveyId);
            if (!isUsed)
            {
                _context.CrmSurveys.Remove(survey);
                await _context.SaveChangesAsync();
            }
            else
            {
                // Return a message saying the survey is in use and cannot be deleted
                return new JsonResult(new { success = false, message = "Survey is in use and cannot be deleted." });
            }
        }

        return new JsonResult(new { success = true });
    }
}
sds
  • 61
  • 7

1 Answers1

0

The URL in your fetch command goes to the root Index page, not the one in the Surveys folder. Change it as follows:

fetch(`?handler=Delete&id=${surveyId}`, ...

If you have issues with asynchronous requests not seeming to work in the future, hit F12 to open the developer tools in Chrome or Edge and check the details in the network tab to see:

  1. if a request is being made
  2. the location being requested
  3. the returned status code.

Doing that would have shown you that the URL for the request was something like

https://localhost:xxxx/Index?handler=delete&surveyid=x

and not what you expected.

Mike Brind
  • 28,238
  • 6
  • 56
  • 88
  • Thank you. That solves the issue though I'm a little confused, in another page I'm using the dot and it resolves to the current page fine, so that threw me off. Here is that code `const response = await fetch('./Details?handler=SaveLineItem&id=${id}', {` and in the network tab this is the request path `https://localhost:7213/Invoices/Details?handler=SaveLineItem&id=231da2cd-c170-43d6-d993-08db96a1582c`. Also, this article implies that the dot is a reference to the same directory for relative paths https://stackoverflow.com/questions/6008829/what-does-a-dot-mean-in-a-url-path. – sds Aug 23 '23 at 14:46
  • These seem to confirm that as well. https://denmchenry.com/posts/relative-urls/ https://stackoverflow.com/questions/7591240/what-does-dot-slash-refer-to-in-terms-of-an-html-file-path-location – sds Aug 23 '23 at 14:56
  • @sds,you could access the page with both https://localhost:xxxx/Surveys or https://localhost:xxxx/Surveys/Index,the issue would occour with the first uri, – Ruikai Feng Aug 24 '23 at 07:59