添加年级及验证视图模型

添加Insert方法

在GradeService中添加Insert中添加Insert方法,代码如下:

public void Insert(GradeViewModel model)
{
    Grade grade = new Grade()
    {
        Name = model.Name,
    };
    gradeRepo.Insert(grade);
}

添加Add动作

在GradeController中添加2个Add动作,代码如下:

public IActionResult Add()
{
    return View();
}

[HttpPost]
public IActionResult Add(GradeViewModel model)
{
    gradeService.Insert(model);
    return RedirectToAction("Index");
}

添加Add视图

在Views创建Add文件夹,并添加视图文件Add.cshtml,代码如下:

@{
    ViewBag.Title = "添加年级";
}
@model GradeViewModel

<form method="post" class="mx-auto" style="width:320px;">
    <div class="field">
        <label asp-for="Name" class="label"></label>
        <div class="control">
            <input asp-for="Name" class="input">
        </div>
    </div>
    <div class="field">
        <button class="button is-primary is-fullwidth">提交</button>
    </div>
</form>

插入空值错误

将地址设置为/Grade/Add,就能访问创建的Add视图。

但是,如果此时什么也不输入,保持输入框为空,直接提交,则会报错,错误如下:

An unhandled exception occurred while processing the request.
SqliteException: SQLite Error 19: 'NOT NULL constraint failed: Grades.Name'.
Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(int rc, sqlite3 db)

DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)

在数据库的Grades表中,也并不会新增数据。

这是因为我们在Grade模型类中设置Name属性string类型,string类型是不能为空的值,只有string?类型才允许为空。

public string Name { get; set; } = string.Empty;

像解决这一问题,一种方法是将string类型改成string?类型。

public string? Name { get; set; } = string.Empty;

但是有时候我们的本意就是不能为空,这时候我们就需要通过视图模型检验值是否为空,如果为空则将错误显示在视图中。

Required特性

在视图模型的属性上添加Required特性,可以在属性值为空时捕获错误。

如果要自定义显示的错误的文本,则可以通过ErrorMessage属性设置。

最终GradeViewModel的代码如下:

public class GradeViewModel
{
    public Guid Id { get; set; }

    [Required(ErrorMessage = "年级不能为空")]
    [Display(Name = "年级")]
    public string Name { get; set; } = string.Empty;
}

验证视图模型

在控制器中,可以通过ModelState.IsValid来验证接收的视图模型数据是否合法,如果合法,才执行相应的操作,否则返回视图。

因此Add动作中的代码可以修改如下:

[HttpPost]
public IActionResult Add(GradeViewModel model)
{
    if (ModelState.IsValid)
    {
        gradeService.Insert(model);
        return RedirectToAction("Index");
    }
    return View(model);
}

显示验证信息

如果视图模型在控制器中没有通过,并且返回视图,应该在视图中将不通过的原因显示出来。

可以在视图中添加asp-validation-summary来显示模型验证不通过的原因。

最终Add.cshtml中的代码修改如下:

<form method="post" class="mx-auto" style="width:320px;">
    <div asp-validation-summary="All" class="has-text-danger mb-4"></div>
    <div class="field">
        <label asp-for="Name" class="label"></label>
        <div class="control">
            <input asp-for="Name" class="input">
        </div>
    </div>
    <div class="field">
        <button class="button is-primary is-fullwidth">提交</button>
    </div>
</form>

最终,当我们提交空值时就会提示年级不能为空

image-20240817235150238

给Major模块添加模型验证

修改MajorViewModel

MajorViewModel代码修改如下:

public class MajorViewModel
{
    public Guid Id { get; set; }

    [Required(ErrorMessage = "专业名称不能为空")]
    [Display(Name = "专业名称")]
    public string Name { get; set; } = string.Empty;
}

修改Add动作

Add动作代码修改如下:

[HttpPost]
public IActionResult Add(MajorViewModel model)
{
    if (ModelState.IsValid)
    {
        majorService.Insert(model);
        return RedirectToAction("Index");
    }
    return View(model);
}

修改Edit动作

Edit动作代码修改如下:

[HttpPost]
public IActionResult Edit(MajorViewModel model)
{
    if (ModelState.IsValid)
    {
        majorService.Update(model);
        return RedirectToAction("Index");
    }
    return View(model);
}

修改视图

在Add.cshtml和Edit.cshtml中相应位置添加如下代码:

<div asp-validation-summary="All" class="has-text-danger mb-4"></div>