I am wanting to post all selected items from a list to a table, creating a new row for each of the selected items. I am having trouble posting multiple items at once however. I have tried to set up the tables to have a relationship using navigation properties but im rather new at this so cannot be sure where I have gone wrong. Currently I am able to post to the database, but only 1 record. The sticking point is posting multiple records to the TblReferrals table.
Please see below my model and page model set ups, so far
public class TblReferrals
{
[Key]
public string? IncidentId { get; set; }
public string AssignmentNumber { get; set; }
}
public class TblReferralStaff
{
public int Id { get; set; }
public string? AssignmentNumber { get; set; }
public TblReferrals TblReferrals { get; set; }
public string? IncidentId { get; set; }
}
My form
<form method="post" id="newReferralForm">
<div class="row my-md-3">
<div class="col-md-6">
<label>Staff Names</label>
<select class="form-control staffReferral" multiple="multiple" asp-items="@Model.EsrRecords" asp-for="@Model.ReferralStaff.AssignmentNumber">
<option></option>
</select>
</div>
</div>
<div class="row my-md-3">
<div class="col-md-6">
<label>Incident Number</label>
<input class="form-control" asp-for="@Model.Referral.IncidentId" />
</div>
</div>
<div class="d-flex justify-content-center mt-5">
<button class="btn btn-primary fw-bold createReferral">Submit</button>
</div>
</form>
My Post request which is not complete, as this is the bit im kind of getting stuck on
[BindProperty]
public List<string> TblStaffList { get; set; }
public SelectList EsrRecords { get; set; }
public async Task<IActionResult> OnPostNewReferral()
{
await _db.TblReferralStaff.AddRangeAsync(ReferralStaff);
await _db.TblReferrals.AddAsync(Referral);
await _db.SaveChangesAsync();
return new JsonResult(ReferralStaff);
}
From your code and description, You are setting a one-to-many relationship in your models https://learn.microsoft.com/en-us/ef/core/modeling/relationships/one-to-many . Here is the modification.
1 The configuration of your models and dbcontext
Tbl Model
public class TblReferrals
{
[Key]
public string? IncidentId { get; set; }
public string AssignmentNumber { get; set; }
public ICollection<TblReferralStaff> TblReferralStaffs { get; } = new List<TblReferralStaff>();
}
public class TblReferralStaff
{
public int Id { get; set; }
public string? AssignmentNumber { get; set; }
public TblReferrals TblReferrals { get; set; } = null!;
public string? IncidentId { get; set; }
}
DbContext
public class MultipleRecordsContext : DbContext
{
public MultipleRecordsContext (DbContextOptions<MultipleRecordsContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TblReferrals>()
.HasMany(e => e.TblReferralStaffs)
.WithOne(e => e.TblReferrals)
.HasForeignKey(e => e.IncidentId)
.IsRequired();
}
public DbSet<MultipleRecords.Models.TblReferrals> TblReferrals { get; set; } = default!;
public DbSet<MultipleRecords.Models.TblReferralStaff> TblReferralStaff { get; set; } = default!;
}
It will generate two tables for you in database, and add the foreign key reference.
2 Bind the correct value in your razor pages
Tbl.cshtml
@page
@model MultipleRecords.Pages.TblModel
@{
}
<h1>This is TblReferrals</h1>
<form method="post" id="newReferralForm">
<div class="row my-md-3">
<div class="col-md-6">
<label>Staff Names</label>
@* For a clearer display, I directly popup the option value with numbers *@
@* Here is the TblStaffList that is bound *@
<select class="form-control staffReferral" multiple="multiple" asp-items="@Model.EsrRecords" asp-for="@Model.TblStaffList">
<option value="1"> Num 1 </option>
<option value="2"> Num 2 </option>
<option value="3"> Num 3 </option>
<option value="4"> Num 4 </option>
</select>
</div>
</div>
<div class="row my-md-3">
<div class="col-md-6">
<label>Incident Number</label>
<input class="form-control" asp-for="@Model.Referral.IncidentId" />
</div>
</div>
<div class="d-flex justify-content-center mt-5">
<button class="btn btn-primary fw-bold createReferral">Submit</button>
</div>
</form>
Tbl.cshtml.cs
public class TblModel : PageModel
{
private readonly MultipleRecordsContext _db;
public TblModel(MultipleRecordsContext db)
{
_db = db;
}
public void OnGet()
{
}
[BindProperty]
public TblReferrals Referral { get; set; }
[BindProperty]
public List<string> TblStaffList { get; set; }
public SelectList EsrRecords { get; set; }
public async Task<IActionResult> OnPostAsync()
{
Console.WriteLine("Post entered");
//Considered that the <select> element with multiple="multiple" attribute can only bind to a list of simple types,
//it is clearer to bind the value to a string list and initialize a referralstaff object
//Your logic code
…
await _db.TblReferrals.AddAsync(referral);
await _db.SaveChangesAsync();
// Create a referral staff record for each selected staff number member.
foreach (var staffAssignmentNumber in TblStaffList)
{
var referralStaff = new TblReferralStaff
{
AssignmentNumber = staffAssignmentNumber,
IncidentId = Referral.IncidentId
};
await _db.TblReferralStaff.AddAsync(referralStaff);
}
await _db.SaveChangesAsync(); // Save referral staff records.
return RedirectToPage("Index");
}
}
Option selected
Value passed
Records stored