I have 2 tables/classes: Films and Actors, and intermediate table relating them. I'm trying to generate a new record into the into the intermediate table to generate a new relationship and add a new film to an actor's filmography.
Here's the ViewModel class:
public class ActorsUpdateFilmsViewModel
{
public Actor actor { get; set; }
public IQueryable<Film> bindedFilms { get; set; }
[DisplayName("Title")]
public int FilmId { get; set; }
public int ActorId;
}
The view where you can choose an unrelated film from a combo box:
<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>
Then the controller which retrieves data:
[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
};
The newBinding item works perfectly for adding it to the intermediate table and bind the actor and the film. But the ModelState.IsValid returns a false. Why? What am I missing?
Thanks
NOTE: I have made a little test and all data is being retrieved and binded, except for the bindedFilms property. Tried to make it an IEnumerable/List, but none of these work. The .Any() function always returns a false
The problem is that you are not binding a corresponding value to @Model.actor.ActorName
which is causing this property to receive null in the controller.
You can add a breakpoint and look at the Values
property under ModelState
to find which model property is Invalid
:
There are two solutions.
The first one, add binding value to @Model.actor.ActorName
in UpdateFilms.cshtml
:
//...
<input type="hidden" asp-for="@Model.actor.ActorName" />
//...
The second one, remove the [Required]
attribute and change the ActorName
property in the Actor
class to be nullable:
[DisplayName("Actor name")]
//[Required]
public string? ActorName { get; set; } = null!;