skip to Main Content

I have 2 models, one for Poll and for PollOption. In the create action, I want to add 1 Poll to the database and a list of PollOptions as well. Each PollOption has a foreign key PollId.

When I submit the form, the modelstate is never set to valid because the Id and ForeignId in the tables are always empty even though I put a hidden input in the HTML. So why is it happening?

Models:

public class Poll
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string Question { get; set; } = "";
}

public class PollOption
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string Option { get; set; } = "";

    [Required]
    public int PollId { get; set; }

    [ForeignKey("PollId")]
    [ValidateNever]
    public Poll Poll { get; set; }
}

View model:

public class PollVM
{
    public Poll Poll { get; set; }

    [ValidateNever]
    public List<PollOption> PollOptions { get; set; }
}

Action:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(PollVM pollVM) {  
   if(ModelState.IsValid)
   {
     pollVM.PollOptions.ForEach(p => p.Poll = pollVM.Poll);
     _unitOfWork.PollOption.AddRange(pollVM.PollOptions);
     _unitOfWork.Save();
     return RedirectToAction("Index");
   }
            
   return View(pollVM);
}

View:

@model PollVM
<div class="index-container">
    <div class="subcontainer">
        <h1 class="title">Poll Creator</h1>
        <h2 class="subtitle">Complete the form below to create your poll!</h2>
        <form method="POST" asp-action="Create">
            <input asp-for="Poll.Id" type="hidden" />
            <div class="form-container">
                <div class="form-input">
                    <label asp-for="Poll.Question">Question:</label>
                    <input asp-for="Poll.Question" type="text" placeholder="Type the poll question here" required>
                </div>
                <div class="form-input">
                    <div class="form-input form-options">
                        <label>Answer Options:</label>
                        <div class="form-option">
                            <input name="PollOptions[0].Id" type="hidden" />
                            <input name="PollOptions[0].PollId" type="hidden" />
                            <input name="PollOptions[0].Option" type="text" placeholder="Option 1" required>
                            <img src="~/images/icons/cross.svg" alt="remove-option" width="30px" class="remove-option" onclick="removeOption(this)">
                        </div>
                        <div class="form-option">
                            <input name="PollOptions[1].Id" type="hidden" />
                            <input name="PollOptions[1].PollId" type="hidden" />
                            <input name="PollOptions[1].Option" type="text" placeholder="Option 2" required>
                            <img src="~/images/icons/cross.svg" alt="remove-option" width="30px" class="remove-option" onclick="removeOption(this)">
                        </div>
                    </div>
                    <button type="button" class="button side-button icon-button">Add Option <img src="~/images/icons/plus.svg" alt="add-option" width="25px"></button>
                </div>
                <button type="submit" class="button submit-button">Create!</button>
            </div>
        </form>
    </div>
</div>

@section Scripts {
    <script src="~/js/answer-options.js" asp-append-version="true"></script>
}

2

Answers


  1. You forget to fill the value for hidden input:
    <input name="PollOptions[0].Id" value="@Model.PollOptions[0].Id" type="hidden"/>

    Login or Signup to reply.
  2. I test it, [ForeignKey()] is not in correct place.

    you must use it above the public int PollId { get; set; } property

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search