У меня есть 2 таблицы/класса: фильмы и актеры, а также промежуточная таблица, связанная с ними. Я пытаюсь создать новую запись в промежуточной таблице, чтобы создать новую связь и добавить новый фильм в фильмографию актера.
Вот класс ViewModel:
public class ActorsUpdateFilmsViewModel
{
public Actor actor { get; set; }
public IQueryable<Film> bindedFilms { get; set; }
[DisplayName("Title")]
public int FilmId { get; set; }
public int ActorId;
}
Представление, в котором вы можете выбрать несвязанный фильм из поля со списком:
<div class = "right">
<div class = "right">
<h3>Add a film:</h3>
<form asp-action = "Bind">
<div asp-validation-summary = "ModelOnly" class = "text-danger"></div>
<div class = "form-group">
<label asp-for = "FilmId" class = "control-label"></label>
<select asp-for = "FilmId" class = "form-control" asp-items = "ViewBag.Unbinded"></select>
<span asp-validation-for = "FilmId" class = "text-danger"></span>
</div>
<input type = "hidden" asp-for = "actor.ActorId" />
<input type = "hidden" asp-for = "@Model.actor" />
<input type = "hidden" asp-for = "@Model.bindedFilms" />
<div class = "form-group">
<input type = "submit" value = "Bind" class = "btn btn-success" />
</div>
</form>
</div>
</div>
Затем контроллер, который извлекает данные:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Bind(int id, [Bind("actor,FilmId,bindedFilms, ActorId")]ActorsUpdateFilmsViewModel model)
{
if (ModelState.IsValid)
{
if (model.FilmId != null)
{
FilmsAndActor newBinding = new FilmsAndActor()
{
FilmIdFk = model.FilmId,
ActorIdFk = model.actor.ActorId
};
Элемент newBinding отлично подходит для добавления его в промежуточную таблицу и связывания актера и фильма. Но ModelState.IsValid возвращает false. Почему? Что мне не хватает?
Спасибо
ПРИМЕЧАНИЕ. Я провел небольшой тест, и все данные извлекаются и привязываются, за исключением свойства bindedFilms. Пытался сделать это IEnumerable/List, но ничего из этого не работает. Функция .Any() всегда возвращает false
В настоящее время нет (я запустил тот же код, но без IsValid, и он работает), или вы имеете в виду присвоить ActorIdFk другое значение, например model.ActorId или id, и посмотреть, как это работает?
Если IsValid равно false, то где-то в ModelState есть свойство, вызывающее проблему.
Что определяет, когда это действительно или нет? Отсутствие нулей, когда свойство определено как не обнуляемое? Я думаю, что я, должно быть, неправильно привязываюсь, может быть, я посылаю что-то неправильное из представления,
Почему вы объявили bindedFilms как IQueryable? Это должен быть IEnumerable или список. Может быть, это проблема.
Все еще выясняю, когда лучше использовать IQueryable или IEnumerable. Список предназначен для отображения фильмографии актера посредством отложенного запроса в представлении, но эту часть я не показывал в вопросе, потому что проблема в привязке. В любом случае, свойство уже изменено на IEnumerable, и все же IsValid имеет значение false.
IQueryable подходит для запроса внешних ресурсов (например, базы данных). Вам необходимо объявить параметры API/метода как IEnumerable (стоит меньше) или List, но не IQueryable. В любом случае, не могли бы вы предоставить проект или необработанную html-форму, которую вы отправляете?
Только что залил на гитхаб. Проблема в ActorsControllers и Actors/UpdateFilms.cshtml github.com/RascalSpark/FilmsWebApp/tree/master/FilmsWebApp
Спасибо за загрузку кода. Как упоминалось выше @Chen. недопустимое состояние вызывается свойством Actor.ActorName, которое помечено как [обязательное]. Решением будет любой из случаев, озвученных Ченом.
Я думаю в этом проблема
<input type = "hidden" asp-for = "actor.ActorId" />
Похоже, вам нужно использовать @Model.ActorId. Пожалуйста, также убедитесь, что между сообщениями не указано значение параметра «Актер».
<input type = "hidden" asp-for = "@Model.actor.ActorId" /> <input type = "hidden" asp-for = "@Model.actor" /> <input type = "hidden" asp-for = "@Model.bindedFilms" /> Все еще IsValid возвращает false Актер не является нулевым, поскольку часть представления, которой я не делился, отображает свойства ViewModel и одно из свойств актеров (имя)
Проблема в том, что вы не привязываете соответствующее значение к @Model.actor.ActorName, из-за чего это свойство получает null в контроллере.
Вы можете добавить точку останова и посмотреть на свойство Values под ModelState, чтобы узнать, какое свойство модели является Invalid:
Есть два решения.
Первый, добавьте значение привязки к @Model.actor.ActorName в UpdateFilms.cshtml:
//...
<input type = "hidden" asp-for = "@Model.actor.ActorName" />
//...
Во-вторых, удалите атрибут [Required] и измените свойство ActorName в классе Actor, чтобы оно допускало значение NULL:
[DisplayName("Actor name")]
//[Required]
public string? ActorName { get; set; } = null!;
Это сработало! Просто знайте: в любом обычном случае, когда я передаю сложный тип (в данном случае объект «актер»), его свойства будут поставляться с привязанным объектом. Проблема заключалась в том, что одно из свойств актора в этом случае было помечено как обязательное, поэтому его нужно было явно отправить из формы, верно? Спасибо!
Да, если это свойство требуется, вам нужно присвоить ему значение, иначе оно будет иметь значение null и не пройдет проверку модели.
Разбейте его там, где вы проверяете IsValid, и посмотрите, какое свойство вызывает ошибку.