Dlaczego ModelState.isValid zwraca false mimo, że w OnPost odczytuję poprawne wartości?

0

Witam. jestem początkującym w net core i możliwe że robię jakiegoś potężnego bubla.

Mam input model:

        public class InputModel
        {
            [Required(ErrorMessage ="Wymagane - Właściciel rezerwacji")]
            [Display(Name ="Właściciel rezerwacji")]
            public string ApplicationUser { get; set; }

            [Required(ErrorMessage ="Wymagane - Sala")]
            [Display(Name ="Wybierz salę")]
            public Guid? Room { get; set; }

            [Required(ErrorMessage ="Wymagane - Data rezerwacji")]
            [Display(Name ="Data rezerwacji")]
            [DataType(DataType.Date, ErrorMessage ="Data jest nieprawidłowa")]
            public DateTime? ReservationDate { get; set; }
        }
        [BindProperty]
        public InputModel Input { get; set; }

Oraz form:

<form method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group" style="background-color:antiquewhite; padding:10px; border-radius:5px; margin-bottom:10px; margin-top:10px">
                <label asp-for="Input.ApplicationUser"></label>
                <select name="SelectedUser" asp-for="Input.ApplicationUser" class="form-control">
                    @if (!(Model.Users is null))
                    {
                        @foreach (var item in Model.Users)
                        {
                            <option value="@item.Id">
                                @Html.DisplayFor(modelItem => item.FirstName) @Html.DisplayFor(modelItem => item.LastName) (@Html.DisplayFor(modelItem => item.Email))
                            </option>
                        }
                    }
                </select>
                <span asp-validation-for="Input.ApplicationUser" class="text-danger"></span>
            </div>
            <div class="form-group" style="background-color:antiquewhite; padding:10px; border-radius:5px; margin-bottom:10px; margin-top:10px">
                <label asp-for="Input.Room"></label>
                <select name="SelectedRoom" asp-for="Input.Room" class="form-control" onchange="this.form.submit()">
                    @if (!(Model.Rooms is null))
                    {
                        <option selected disabled>Wybierz pokój</option>
                        @foreach (var item in Model.Rooms)
                        {
                            <option class="form-control" value="@item.ID">
                                @Html.DisplayFor(modelItem => item.Name) - @Html.DisplayFor(modelItem => item.Price)zł/55min.
                            </option>
                        }
                    }
                </select>
                <span asp-validation-for="Input.Room" class="text-danger"></span>
            </div>
            <div class="form-group" style="background-color:antiquewhite; padding:10px; border-radius:5px; margin-bottom:10px; margin-top:10px">
                <label asp-for="Input.ReservationDate"></label>
                <input name="SelectedDate" asp-for="Input.ReservationDate" type="text" class="form-control" id="datepicker" placeholder="dd.mm.rrrr" onchange="this.form.submit()" />
                <span asp-validation-for="Input.ReservationDate" class="text-danger"></span>
            </div>
        </form>

OnPost

public async Task<IActionResult> OnPost(Guid? SelectedRoom, DateTime? SelectedDate, string SelectedUser)
        {
            
            ApplicationUser user = await _userManager.FindByIdAsync(SelectedUser);
            await LoadAsync(user);
            Input.ApplicationUser = SelectedUser;
            Input.Room = SelectedRoom;
            if (!SelectedDate.HasValue)
                SelectedDate = DateTime.Now.Date;
            if (DateTime.Compare(SelectedDate.Value, new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day)) > 0)
                Input.ReservationDate = SelectedDate;
            else
                Input.ReservationDate = DateTime.Now.Date;

            if (!ModelState.IsValid)
            {
                //StatusMessage = "Model błędny: Room(" + Input.Room + "), Date(" + Input.ReservationDate.ToString() + ")";
                foreach (var val in ModelState.Values)
                {
                    foreach(var err in val.Errors)
                        ModelState.AddModelError(string.Empty, err.ErrorMessage);
                }
                return Page();
            }

            Room room = _dbContext.Rooms.FirstOrDefault(x => x.ID == SelectedRoom);
            if (room == null)
                return Page();
            _reservationService.GetAvailableReservationHours(room, SelectedDate.Value);
            return Page();
        }

Podczas zmiany daty (datepicker) lub sali (dropdownlist) wywołuje się OnPost. wewnątrz OnPost mogę prawidłowo odczytać wartości z Input, jednak modelValidation cały czas generuje mi błędy. Nie potrafię odnaleźć przyczyny błędu. Jeżeli potrzebujecie jakiś dodatkowych informacji aby udzielić mi pomocy piszcie w komentarzu. Dziękuję z góry ^^
screenshot-20200624120206.png

1

Wydaję mi się, że nie możesz używać takiego podwójnego bindowania. Musisz się zdecydować czy używasz [BindProperty] public InputModel Input { get; set; } czy przekazujesz zmienne jako parametry do metody OnPost.

0

Wygląda na to, że właściwości w klasie Input ** nie są ustawiane wcale. Dodatkowo nie mam żadnych elementów w listach. W tym momencieOnPost**:

public async Task<IActionResult> OnPost()
        {
            ApplicationUser user = await _userManager.FindByIdAsync(Input.ApplicationUser);
            if(user == null)
            {
                ModelState.AddModelError(string.Empty, "Nie znaleziono użytkownika" + Input.ApplicationUser);
                return Page();
            }
            await LoadAsync(user);
            if (!ModelState.IsValid)
            {
                foreach (var val in ModelState.Values)
                {
                    foreach (var err in val.Errors)
                        ModelState.AddModelError(string.Empty, err.ErrorMessage);
                }
                return Page();
            }
            if (DateTime.Compare(Input.ReservationDate.Value, new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day)) > 0)
            {
                ModelState.AddModelError(string.Empty, "Nieprawidłowa data rezerwacji");
                return Page();
            }
            Room room = _dbContext.Rooms.FirstOrDefault(x => x.ID == Input.Room);
            if (room == null)
            {
                ModelState.AddModelError(string.Empty, "Sala o podanej nazwie nie istnieje");
                return Page();
            }  
            _reservationService.GetAvailableReservationHours(room, Input.ReservationDate.Value);
            return Page();
        }

Oraz uzupełnianie list:

private async Task LoadAsync(ApplicationUser user)
        {
            Rooms = await _dbContext.Rooms.ToListAsync();
            AdminOptionEnabled = await _userManager.IsInRoleAsync(user, "Admin");
            if (AdminOptionEnabled)
            {
                Users = await _dbContext.Users.ToListAsync();            
            }
            else
            {
                Users = new List<ApplicationUser>();
                Users.Add(user);
            }
        }

Przy wyświetleniu błędu powinno być id użytkownika, jednak nie ma go wcale
screenshot-20200624133420.png

EDIT:
problem rozwiązany: @Kokoniłaj miał rację. jednak dodatkowo jeszcze musiałem usunąć Nazwy komponentów
name="SelectedUser"
name="SelectedRoom"
name="SelectedDate"

1 użytkowników online, w tym zalogowanych: 0, gości: 1