删除学生

添加Delete方法

在StudentService中添加Delete方法。

该方法接收一个Guid类型的参数id,并获取对应的数据。

如果数据不存在,则抛出空引用异常。

如果数据存在,则删除。

代码如下:

public void Delete(Guid id)
{
    Student? student = studentRepo.Get(id);
    if (student == null)
    {
        throw new NullReferenceException("未找到该学生,无法删除");
    }
    studentRepo.Delete(student);
}

创建Delete动作

在StudentController中创建Delete动作。

此动作同样接收Guid类型的参数id,并尝试调用StudentService的Delete方法。

如果没有发生异常,则return Ok("删除成功"),表示返回状态码200并附加文本信息。

如果发生异常,则return BadRequest(ex.Message),表示返回状态码400并附加错误信息文本。

代码如下:

public IActionResult Delete(Guid id)
{
    try
    {
        studentService.Delete(id);
        return Ok("删除成功");
    }
    catch (NullReferenceException ex)
    {
        return BadRequest(ex.Message);
    }
}

添加删除按钮

在Index.cshtml的编辑按钮后面添加一个删除按钮,代码如下:

<td>
    <a asp-action="Edit" asp-route-id="@student.Id" class="button is-warning">编辑</a>
    <button class="button is-danger" onclick="Delete('@student.Id')">删除</button>
</td>

onclick="Delete('@student.Id')"表示点击此按钮会调用JavaScript的Delete函数,并将学生Id作为参数传入。

这个函数会在后面编写。

添加Scripts Section

在_Layout.cshtml布局文件中,有一个语句:

@await RenderSectionAsync("Scripts", false)

现在我们在视图中添加对应的部分。

在Index.cshtml底部添加如下代码:

@section Scripts {

}

这样,其中的代码会在布局代码的@await RenderSectionAsync("Scripts", false)部分加载。

添加Delete函数

在@section Scripts中添加Delete函数,代码如下:

function Delete(id) {

}

添加弹窗

在Delete函数中添加sweetalert2代码实现弹窗,代码如下:

Swal.fire({
    title: "是否确定删除?",
    text: "此操作不可撤销!",
    icon: "warning",
    showCancelButton: true,
    confirmButtonText: "是",
    cancelButtonText: "否",
    animation: false
});

每个配置的含义如下:

  • title:弹窗的标题
  • text:弹窗的文本
  • icon:弹窗的图标
  • showCancelButton:是否显示取消弹窗的按钮
  • confirmButtonText:确认按钮的文本
  • cancelButtonText:取消按钮的文本
  • animation:是否显示动画,默认是true

点击删除按钮后,会出现以下弹窗:

image-20240818193848314

判断是否确认

Swal.fire({
    title: "是否确定删除?",
    text: "此操作不可撤销!",
    icon: "warning",
    showCancelButton: true,
    confirmButtonText: "是",
    cancelButtonText: "否",
    animation: false
}).then(result => {
    if (result.isConfirmed) {
        console.log("确认");
    }
});

通过then可以获取result,通过result.isConfirmed可以判断点击了哪一个按钮。

调用删除接口

如果确认,则通过fetch函数调用删除接口,代码如下:

if (result.isConfirmed) {
    fetch('/Student/Delete/' + id);
}

成功响应后的处理

fetch('/Student/Delete/' + id)
    .then(response => {
        if (response.ok) {
            return response.text().then(text => {
                Swal.fire({
                    title: text,
                    icon: "success"
                }).then(() => location.reload());
            });
        }
    });

如果响应的状态码为200,则response.ok为true。

这时会获取相应文本,并创建新的弹窗,显示文本。

在点击确认按钮后,还会刷新页面,这样会显示删除数据后的列表。

失败响应后的处理

if (response.ok) {
    return response.text().then(text => {
        Swal.fire({
            title: text,
            icon: "success"
        }).then(() => location.reload());
    });
} else {
    return response.text().then(text => {
        Swal.fire({
            title: "删除失败",
            text: text,
            icon: "error"
        });
    });
}

如果相应的状态码为400,则则response.ok为false。

同样会弹窗,并显示错误信息。

最终Delete函数的代码如下:

function Delete(id) {
    Swal.fire({
        title: "是否确定删除?",
        text: "此操作不可撤销!",
        icon: "warning",
        showCancelButton: true,
        confirmButtonText: "是",
        cancelButtonText: "否",
        animation: false
    }).then(result => {
        if (result.isConfirmed) {
            fetch('/Student/Delete/' + id)
                .then(response => {
                    if (response.ok) {
                        return response.text().then(text => {
                            Swal.fire({
                                title: text,
                                icon: "success"
                            }).then(() => location.reload());
                        });
                    } else {
                        return response.text().then(text => {
                            Swal.fire({
                                title: "删除失败",
                                text: text,
                                icon: "error"
                            });
                        });
                    }
                });
        }
    });
}

封装方法

可以将Delete函数封装在main.js中,这样后面的删除功能就能很轻松地调用此函数,不用重新再写一遍。

在wwwroot中创建main.js文件,并创建DeleteWithController方法。

代码如下:

function DeleteWithController(id,controller) {
    Swal.fire({
        title: "是否确定删除?",
        text: "此操作不可撤销!",
        icon: "warning",
        showCancelButton: true,
        confirmButtonText: "是",
        cancelButtonText: "否",
        animation: false
    }).then(result => {
        if (result.isConfirmed) {
            fetch('/' + controller + '/Delete/' + id)
                .then(response => {
                    if (response.ok) {
                        return response.text().then(text => {
                            Swal.fire({
                                title: text,
                                icon: "success"
                            }).then(() => location.reload());
                        });
                    }
                    else {
                        return response.text().then(text => {
                            Swal.fire({
                                title: "删除失败",
                                text: text,
                                icon: "error"
                            });
                        });
                    }
                });
        }
    });
}

这样,之后可以通过传入控制器的名称来控制调用哪个控制器的Delete动作。

引入main.js

将main.js拖入布局文件的head标签中:

<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link href="~/bulma/bulma.css" rel="stylesheet" />
    <script src="~/sweetalert2.all.js"></script>
    <script src="~/htmx.js"></script>
    <script src="~/main.js"></script>
</head>

改写脚本代码

在Index.cshtml中,调用封装后的DeleteWithController函数,代码如下:

@section Scripts {
    <script>
        function Delete(id) {
            DeleteWithController(id, 'Student');
        }
    </script>
}

第二个参数'Student'表示调用StudentController中的Delete动作。