I am trying to select multiple values with Multiselect functionality and pass them to db, but to no avail.
Models' M-M relations
public class Cluster : IEntityBase<string>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id { get; set; }
[Required]
public string Name { get; set; }
public IEnumerable<Sensor> Sensors { get; set; }
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id { get; set; }
public string Name { get; set; }
public IEnumerable<Cluster> Clusters { get; set; }
[ForeignKey("SensorType")]
public string SensorTypeId { get; set; }
public SensorType SensorType { get; set; }
Repository Pattern
private readonly ApplicationDbContext _db;
public SensorRepository(ApplicationDbContext db) {
_db = db;
}
public void Add(SensorVM entity)
{
Sensor mappedSensor = new Sensor()
{
Id = entity.Id,
Name = entity.Name,
Clusters = entity.Clusters,
SensorTypeId = entity.SensorTypeId,
SensorType = entity.SensorType,
APIUrl = entity.APIUrl,
X = entity.X,
Y = entity.Y,
Configuration = entity.Configuration,
ConfigurationSchema = schema.ToJson(),
SerialNumber = entity.SerialNumber,
Interval = entity.Interval,
IsActive = entity.IsActive
};
_db.Sensors.Add(mappedSensor);
_db.SaveChanges();
}
Controller code
[HttpGet]
public IActionResult Add()
{
IEnumerable<Cluster> getClusters = _clusterRepository.GetAll().ToList();
ViewData["Clusters"] = new MultiSelectList(getClusters, "Id", "Name");
...
return View();
}
[HttpPost]
public IActionResult Add(SensorVM obj)
{
if (ModelState.IsValid)
{
_sensorRepository.Add(obj);
return RedirectToAction("Index");
}
return View(obj);
}
View code
<div class="form-floating py-2 col-12">
<select asp-for="Clusters" asp-items="(MultiSelectList)@ViewData["Clusters"]" multiselect-search="true" multiple placeholder="-Select Clusters-">
<span asp-validation-for="Clusters" class="text-danger"></span>
</select>
</div>
It shows Clusters = null.
I suspect I am missing some sort of Id manipulation - collecting them in a list. Using the M-m relationship, a ClusterSensor table was created in db consisting of SensorId and ClusterId.
The other thing is that I am missing a way to populate the 'selectedValues' parameter of MultiSelectList.
public MultiSelectList(IEnumerable items, string dataValueField, string dataTextField, IEnumerable selectedValues);
If you want to get a multi selection of values ,like ClusterIds,we can add a property ClusterIds
in SensorVM model like:
public IEnumerable<Cluster> Clusters { get; set; }
public string[] ClusterIds { get; set; }
Then in the view:
<div class="form-floating py-2 col-12">
<select asp-for="ClusterIds" asp-items="(MultiSelectList)@ViewData["Clusters"]" multiselect-search="true" multiple placeholder="-Select Clusters-">
<span asp-validation-for="ClusterIds" class="text-danger"></span>
</select>
</div>
result:
Then set the Clusters by the select ClusterId, like:
[HttpPost]
public IActionResult Add(SensorVM obj)
{
IEnumerable<Cluster> getClusters = _clusterRepository.GetAll().ToList();
var list = new List<Cluster>();
foreach (var x in obj.ClusterIds)
{
var item = getClusters.FirstOrDefault(s => s.Id == x);
list.Add(item);
}
obj.Clusters = list;
ModelState.Remove("Clusters");
if (ModelState.IsValid)
{
_sensorRepository.Add(obj);
return RedirectToAction("Index");
}
return View(obj);
}
result:
Update:
@model SensorVM
<form method="post">
<div class="form-floating py-2 col-12">
<select asp-for="ClusterIds" asp-items="(MultiSelectList)@ViewData["Clusters"]" multiselect-search="true" multiple placeholder="-Select Clusters-">
<span asp-validation-for="ClusterIds" class="text-danger"></span>
</select>
</div>
<button type="submit">submit</button>
</form>