I have a many to many relationship in a razor page project that joins Roles (UserRoles) to Apps for permissions reasons in a larger project. I'm trying to get a kendo multi select control to read and write to the database via the model. I can do it with checkboxes, but there are too many entries and I need to use a multiselect drop down instead. I cannot get any help from Telerik other than hard coded array data displaying and not saving, which is of no use. I need to read and write assigned values from and to the database.
The code below basically shows what I am trying to do: selectedRoles needs to be an array or list of integers that are selected RoleID's from the database. In PopulateAssignedAppRoleData below they are reading correctly into the AssignedAppRoleDataList where it calls Assigned = appRoles.Contains(role.ID). However selectedRoles needs to resize to accept new RoleID's as I loop through the join table.
I'm not sure where or how to declare public int[] selectedRoles after I know how many integers it needs to hold, or whether I need to use a List<> or enumerable that I can resize dynamically, or whether I need a counter and then another void to populate in a repeat of the loop or.... :(
selectedRoles.Append (role.ID); does not work
public void UpdateAppRoles(FliveRetryContext context, string[] selectedRoles, App appToUpdate) is working correctly to save to database, I just need to fill the array or list to populate the selected values in drop down list.
Thank you for your help, my C# is fairly basic.
I haven't include all of the models, they aren't relevant but they all work
This is the call in the View:
@(Html.Kendo().MultiSelectFor(m=>m.selectedRoles)
.Placeholder("Select ...")
.DataTextField("Role")
.DataValueField("RoleID")
.BindTo(Model.AssignedAppRoleDataList)
and these are the calls in the page model: UpdateAppRoles works fine
public int[] selectedRoles = new int[] {};
public void PopulateAssignedAppRoleData(FliveRetryContext context, App app)
{
var allRoles = context.Role;
var appRoles = new HashSet<int>(
app.RoleAppJoins.Select(c => c.RoleID));
AssignedAppRoleDataList = new List<AssignedAppRoleData>();
foreach (var role in allRoles)
{
AssignedAppRoleDataList.Add(new AssignedAppRoleData
{
RoleID = role.ID,
Role = role.RoleName,
Assigned = appRoles.Contains(role.ID)
});
//This is where I need to append or count, but I don't know the syntax
if (appRoles.Contains(role.ID))
{
selectedRoles.Append (role.ID);
}
}
}
public void UpdateAppRoles(FliveRetryContext context,
string[] selectedRoles, App appToUpdate)
{
if (selectedRoles == null)
{
appToUpdate.RoleAppJoins = new List<RoleAppJoin>();
return;
}
var selectedRolesHS = new HashSet<string>(selectedRoles);
var appRoles = new HashSet<int>
(appToUpdate.RoleAppJoins.Select(c => c.Role.ID));
foreach (var role in context.Role)
{
if (selectedRolesHS.Contains(role.ID.ToString()))
{
if (!appRoles.Contains(role.ID))
{
appToUpdate.RoleAppJoins.Add(
new RoleAppJoin
{
AppID = appToUpdate.ID,
RoleID = role.ID
});
}
}
else
{
if (appRoles.Contains(role.ID))
{
RoleAppJoin roleToRemove
= appToUpdate
.RoleAppJoins
.SingleOrDefault(i => i.RoleID == role.ID);
context.Remove(roleToRemove);
}
}
}
}
Thanks to anyone that considered this, but I got it working
added a new class:
public class SelectedAppRoles
{
public int RoleID { get; set; }
}
Then a new list
public List<SelectedAppRoles> selectedRoles;
Then used the list instead of an array
foreach (var role in allRoles)
{
AssignedAppRoleDataList.Add(new AssignedAppRoleData
{
RoleID = role.ID,
Role = role.RoleName,
Assigned = appRoles.Contains(role.ID)
});
if (appRoles.Contains(role.ID))
{
selectedRoles.Add(new SelectedAppRoles
{
RoleID = role.ID,
});
}
}