I have a multi-select dropdown that I need to grab the values from and place in another data table – the Incident table.
I am pulling the values for the dropdown from this model:
using System.ComponentModel.DataAnnotations;
namespace DWITracker.Model
{
public class Charge
{
[Key]
public int Id { get; set; }
[Required]
[Display(Name = "Charge")]
public string ChargeCode { get; set; }
[Required]
[Display(Name = "Charge Description")]
public string ChargeDesc { get; set; }
}
}
And this is my Create.cs:
using DWITracker.Data;
using DWITracker.Model;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
namespace DWITracker.Pages.Incidents;
[BindProperties]
public class CreateModel : PageModel
{
private readonly ApplicationDbContext _db;
public Incident Incident { get; set; }
public CreateModel(ApplicationDbContext db)
{
_db = db;
}
public IEnumerable<City> DisplayPIAddressCityData { get; set; }
public IEnumerable<County> DisplayPIAddressCountyData { get; set; }
public IEnumerable<Ethnicity> DisplayPIEthnicityData { get; set; }
public IEnumerable<int> Charge { get; set; }
public IEnumerable<SelectListItem> ChargeList { get; set; }
public async Task<PageResult> OnGet()
{
await _db.City.Select(a => a.CityName).ToListAsync();
DisplayPIAddressCityData = await _db.City.ToListAsync();
await _db.County.Select(a => a.CountyName).ToListAsync();
DisplayPIAddressCountyData = await _db.County.ToListAsync();
await _db.Ethnicity.Select(a => a.EthnicityName).ToListAsync();
DisplayPIEthnicityData = await _db.Ethnicity.ToListAsync();
var charges = from c in _db.Charge
select c;
ChargeList = charges.Select(c => new SelectListItem { Value = c.Id.ToString(), Text = c.ChargeCode });
return Page();
}
public async Task<IActionResult> OnPost()
{
await _db.Incident.AddAsync(Incident);
await _db.SaveChangesAsync();
TempData["success"] = "Incident Information added successfully.";
return RedirectToPage("Index");
}
}
And here is the relevant part of my view:
<td style="width: 40%">
<div class="mb-3">
<label asp-for="Incident.ArrestCharges" class="control-label"></label>
<select asp-for="Incident.ArrestCharges" class="form-select" multiple="multiple" asp-items="Model.ChargeList">
<option value="">Select Applicable Charge(s)</option>
</select>
</div>
</td>
Right now, if I select more than one item from the multi-select dropdown, it places the Id value of only the FIRST selection made into the Incident.ArrestCharges column.
I would like it to place a comma separated list of multiple charge codes (not IDs) that would look like this as an example: VTL 1192-1, VTL 1192-2, VTL 1192-2
Would appreciate some guidance in what I need to remove, add or change. This is my first time creating a multi-select dropdown and binding it. Thank you!
2
Answers
Ok, so if user selects 2, or 1 or 5 options?
Then you will need to add 2, or 1 or 5 recrods here.
You can NOT do this:
Eg: tblPeople
So, by storing 3 values (of hotels I am booked to), then now what?
How you going to report, or query or use sql to query what Hotels I am booked into?
Answer: you can’t!!!
So, do NOT just out of the blue start shoving multiple ID’s into ONE column, since then you just broken all possibilities of using SQL to query that data.
In other words, you going to break your relational model, and you do that, then your whole system can’t report on say what hotels I am booked into (in above example).
And since the column data type is a "number" and "id"? Then of course you can’t just shove in multiple ID values. You COULD as my above example shows shove in multiple values if using a string for that column, but as noted, the INSTANT you do that? that is the very same instant you broken the relational model, but it not really about some relational "mumbo-jumbo", but now that you have no practical means to use sql to query that data. (and even translate the "id’s" back into their correct values for display in reports or even in a web page.
So in above, if I want to allow the person to be booked into multiple hotels, I can’t just out of the blue shove in multiple values, but will need to create a new child table. In my exmaple, it would be
tblPeople – my above information about the person.
tblPeopleBookedInhotels – this is the new child table.
So, in place of above, (where I attempted to shove in multiple id’s into that column, I will now have this:
So, old:
New:
So, you can see the "instant" we want multiple hotels to be booked, then we can’t use the one column (hotel_id) that used to save ONE value and ONE id.
The issue is even worse, since your column data type is no doubt a number type, and thus you can’t even shove in a string of "id’s" anyway.
And worse yet, you don’t want to do that, since then any and all ability to query that data also goes out the window.
So, don’t shove multiple values into that one column (that does not allow multiple values).
you will have to get the user selections, AND THEN LOOP over the selections, adding a whole new row to this new table that now can contain a "list" of many hotel bookings.
I mean, you can try can kluge this, and change that one column type from a "number" to a string, and then try to shove in multiple values as a string, but you then break all existing software that assumed and expected ONLY one "id" value in that column.
Edit: Example to write out many rows
Ok, so assume we have "people", and then that listbox of hotels they want to visit or whatever.
So, we have this:
So, we will have People, a table of hotels, and then of course our table that allows each person to have mutliple hotel bookings.
So, tblHotelsBooked.
we in effect have this:
So, say we have some markup to display the Person.
Nothing special, just some markup, AND ALSO that listbox of hotels.
so, we have this markup (not all that important).
Ok, so our code has to load hte one person, and load up the listbox of hotels we want to choose.
So, code to load is this:
And now we see/have this:
So, the save code has to:
Save any edits to the one person, and THEN write out a new row for each hotel selected in the listbox.
So, the save code is this:
So, now we written out a row of data for each selected hotel.
However, in this example?
Our problem now is WHEN we go back to the page to edit again.
We will now have to not only load the one reocrd to edit, but ALSO then load up the list box with possible choices, and ALSO select/highlight each existing hotel so the user can "see" and "know" which options are selected.
And if the user un-selects a hotel, then we have to remove/delete that child row from our tblHotelsBooked.
Now, if this was just a single value (like favorote food), or some such, then that UI can be rather nice. However, in my case, given we are selecting (and adding) hotels to the give user?).
Then we REALLY need to adopt a UI in which the user can see what hotels, and add more hotels, and remove hotels.
So, really, the listbox should become a table like view (say a grid view).
So, THEN when we return to that reocrd, we can more clear see, choose, add, remove, edit, change that information.
So, really, we should dump the listbox, and use a grid of some type.
The result then would be this:
Now, in above example, we kind of have "more" then the selected list.
So, if we were to JUST have a listbox with selected hotels? Sure, but we kind of need "more" in this example, since I want to add more hotels, or remove them.
So, if we "stick" to the list box?
Then we need to add code to select-highlight existing selections.
then we need to add code to "delete" a child row when we un-select.
That is because your dropdown value has been set with the Id, change the value to
ChargeCode
like below:And the multiple dropdownlist should match
List<string>
type property from your requirement, so you need create a separateList<string>
property to receive the multiple selected value and then convert this list to string with comma. At last you can set this string value toIncident.ArrestCharges
.Here is a whole working demo you could follow:
Page
PageModel