ModelState.IsValid в ASP.NET Core работает некорректно

С ASP.NET Core начала работать недавно, так что многое не понимаю. Требуется создать небольшое веб-приложение, которое выводит информацию, вписанную в форму. Код написала, у моей подруги что-то похожее, у неё всё работает. Но я застреваю на валидации.

Когда я ввожу полностью корректную информацию, страница не обновляется, ничего не появляется. Когда убрала ModelState.IsValid, всё заработало, но никакой проверки на правильность введённых данных не проходило (логично). Попробовала по одной проверке валидации у каждого значения убрать, но сколько бы я не убирала, ничего не меняется. Добавляла скрипты JS на проверку валидации, но и они успеха не приносили. По одному удаляла input каждого типа, пока и они не закончились - ничего. Кто-то в интернете посоветовал добавить ко всем типам вводимых значений вопросительный знак, хотя не вижу в этом смысла, ведь Required и должен NULL проверять. В любом случае, тоже не работает. Потом добавила пару строчек с выводом в консоль значений, если валидация проходила успешно и если нет, и что бы я не делала, валидация никогда не проходила.

Пришла к выводу, что вся проблема в ModelState.IsValid. Что-то в моих значениях ему не нравится. Бьюсь с этой фигнёй 4-ый час. Подскажите, пожалуйста, добрые люди(

Код Index.cshtml.cs:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace ЛР2.Pages
{
    public class IndexModel : PageModel
    {
        [BindProperty]
        public List_Replace replace_obj { get; set; }
        public IActionResult OnPost()
        {
            if (ModelState.IsValid)
            {
                replace_list.Replace_List.Add(replace_obj);
                Console.WriteLine("1");
                return RedirectToPage("Index");
            }
            Console.WriteLine("2");
            return Page();
        }
    }
}

Код Index.cshtml:

@page
@model IndexModel
@{
ViewData["Title"] = "Шутова Таисия, ПРИ-122";
}
<script src="~/Scripts/jquery.js"></script>
<script src="~/Scripts/jquery.validation.js"></script>
<script src="~/Scripts/jquery.validation.unobtrusive.js"></script>

<div class="text-center" style="background-color: #f1f5ff">
<h1 class="display-4">Лист замены</h1>

<form method="post" asp-antiforgery="true">
<validation-summary class="text-danger" />

<h4>Запланировано в расписании</h4>
    <input asp-for="replace_obj.Date" placeholder="Дата" />
    <span asp-validation-for="replace_obj.Date" class="text-danger"></span>
    <br />
    <input asp-for="replace_obj.Group" placeholder="Группа" />
    <span asp-validation-for="replace_obj.Group" class="text-danger"></span>
    <br />
    <input asp-for="replace_obj.Duration" placeholder="Часы" />
    <span asp-validation-for="replace_obj.Duration" class="text-danger"></span>
    <br />
    <input asp-for="replace_obj.ClassRoom" placeholder="Аудитория" />
    <span asp-validation-for="replace_obj.ClassRoom" class="text-danger"></span>
    <br />
    <input asp-for="replace_obj.Subject" placeholder="Дисциплина" />
    <span asp-validation-for="replace_obj.Subject" class="text-danger"></span>
    <br />
    <input asp-for="replace_obj.Fio" placeholder="ФИО преподавателя" />
    <span asp-validation-for="replace_obj.Fio" class="text-danger"></span>
    <br />
<h4>Необходимо поставить</h4>
    <input asp-for="replace_obj.NewDate" placeholder="Дата" />
    <span asp-validation-for="replace_obj.NewDate" class="text-danger"></span>
    <br />
    <input asp-for="replace_obj.NewDuration" placeholder="Часы" />
    <span asp-validation-for="replace_obj.NewDuration" class="text-danger"></span>
    <br />
    <input asp-for="replace_obj.NewClassRoom" placeholder="Аудитория" />
    <span asp-validation-for="replace_obj.NewClassRoom" class="text-danger"></span>
    <br />
    <input asp-for="replace_obj.NewSubject" placeholder="Дисциплина" />
    <span asp-validation-for="replace_obj.NewSubject" class="text-danger"></span>
    <br />
    <input asp-for="replace_obj.NewFio" placeholder="ФИО преподавателя" />
    <span asp-validation-for="replace_obj.NewFio" class="text-danger"></span>
    <br />
    <input asp-for="replace_obj.Reason" placeholder="Причина замены" />
    <span asp-validation-for="replace_obj.Reason" class="text-danger"></span>
    <br />
<button type="submit">Добавить замену</button>

</form>

<table width="100%">
    <thead>
    </thead>
    <tbody>
        @foreach (var listItem in replace_list.Replace_List)
        {
            <tr>
                <th style="background-color: #d0e3f7"><h3>Лист замены</h3></th>
            </tr>
            <tr style="background-color: #f0f8ff">
                <td>
                    <h4>Запланировано в расписании</h4>
                    <div> Дата: @listItem.Date.ToString("d")</div>
                    <div> Группа: @listItem.Group</div>
                    <div> Время: @listItem.Duration</div>
                    <div> Аудитория: @listItem.ClassRoom</div>
                    <div> Дисциплина: @listItem.Subject</div>
                    <div> ФИО преподавателя: @listItem.Fio</div>
                    <h4>Необходимо поставить</h4>
                    <div> Дата: @listItem.NewDate.ToString("d")</div>
                    <div> Время: @listItem.NewDuration</div>
                    <div> Аудитория: @listItem.NewClassRoom</div>
                    <div> Дисциплина: @listItem.NewSubject</div>
                    <div> ФИО преподавателя: @listItem.NewFio</div>
                    <div> Причина: @listItem.Reason</div>
                </td>
            </tr>
        }
    </tbody>
</table>

</div>

Код List_Replace.cs:

using System.ComponentModel.DataAnnotations;

namespace ЛР2
{
    public class List_Replace
    {
        [Required(ErrorMessage = "Введите дату")]
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        [Range(typeof(DateTime), "2019-01-01", "9999-12-31", ErrorMessage = "Нельзя выбрать дату раньше 2019 года")]
        public DateTime Date { get; set; }


        [Required(ErrorMessage = "Введите название группы")]
        public string? Group { get; set; }

        [Required(ErrorMessage = "Введите время начала и окончания пары в формате HH:MM-hh:mm")]
        [Duration]
        public string? Duration { get; set; }


        [Required(ErrorMessage = "Введите номер кабинета")]
        public string? ClassRoom { get; set; }


        [Required(ErrorMessage = "Введите название дисциплины")]
        public string? Subject { get; set; }


        [Required(ErrorMessage = "Введите ФИО преподавателя")]
        public string? Fio { get; set; }

        [Required(ErrorMessage = "Введите дату")]
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        [Range(typeof(DateTime), "2019-01-01", "9999-12-31", ErrorMessage = "Нельзя выбрать дату раньше 2019 года")]
        public DateTime NewDate { get; set; }


        [Required(ErrorMessage = "Введите название группы")]
        public string? NewGroup { get; set; }

        [Required(ErrorMessage = "Введите время начала и окончания пары в формате HH:MM-hh:mm")]
        [Duration]
        public string? NewDuration { get; set; }


        [Required(ErrorMessage = "Введите номер кабинета")]
        public string? NewClassRoom { get; set; }


        [Required(ErrorMessage = "Введите название дисциплины")]
        public string? NewSubject { get; set; }


        [Required(ErrorMessage = "Введите ФИО преподавателя")]
        public string? NewFio { get; set; }

        [Required(ErrorMessage = "Введите причину замены")]
        public string? Reason { get; set; }

    }

    public class replace_list
    {
        public static List<List_Replace> Replace_List = new List<List_Replace>();
    }

    public class DurationAttribute : ValidationAttribute
    {
        public override bool IsValid(object? value)
        {
            if (value is string duration)
            {
                string[] times = duration.Split('-');
                if (times.Length == 2)
                {
                    TimeSpan start = TimeSpan.Parse(times[0]);
                    TimeSpan end = TimeSpan.Parse(times[1]);
                    TimeSpan finDuration = end - start;
                    if (finDuration == TimeSpan.FromHours(1.5)) {
                        return true;
                    } else
                    {
                        ErrorMessage = "Пара должна длиться 1 час 30 минут";
                    }
                } else {
                    ErrorMessage = "Некорректный формат времени. Введите в виде HH:MM-hh:mm";
                }
            }
            return false;
        }
    }
}

Ответы (0 шт):