I have a Blazor component where I use an InputSelect to allow users to select a role for a user. The issue is that the @bind-Value of the InputSelect does not update the SelectedRole variable as expected. When I try to save the changes, the role that gets saved is the initially selected role, not the one chosen in the dropdown.
Here it is part of my code:
<div class="row">
<div class="col-md-4">
<EditForm method="post" Model="User" OnValidSubmit="SaveChanges" FormName="EditUserForm">
<DataAnnotationsValidator />
<ValidationSummary role="alert" />
<div class="mb-3">
<label for="username" class="form-label">Nome</label>
<InputText id="username" @bind-Value="User.UserName" class="form-control" readonly />
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<InputText id="email" @bind-Value="User.Email" class="form-control" readonly />
</div>
<div class="mb-3">
<label for="role" class="form-label">Selecionar Role:</label>
<InputSelect id="role" @bind-Value="SelectedRole" class="form-group" >
<option value="-1">Nenhum</option>
@foreach (var role in AllRoles)
{
<option value="@role.Name">@role.Name</option>
}
</InputSelect>
</div>
<p>Selected Role: @SelectedRole</p>
<button type="submit" class="btn btn-primary"><img title="Gravar" src="/img/saveicon.png" style="height:30px" /></button>
<a href="/GereUsers" type="button" class="btn btn-outline-secondary"><img title="Recuar" src="/img/backicon.png" style="height:30px" /></a>
</EditForm>
</div>
</div>
}
<p class="text-info">@DebugMessage</p>
@code {
[SupplyParameterFromQuery]
private string? Id { get; set; }
private ApplicationUser? User;
private List<IdentityRole> AllRoles = new();
private string? SelectedRole;
private string DebugMessage { get; set; } = "Inicializando...";
protected override async Task OnInitializedAsync()
{
if (Id is not null)
{
User = await UserManager.FindByIdAsync(Id);
if (User is null)
{
DebugMessage = "Usuário não encontrado.";
NavigationManager.NavigateTo("/notfound");
return;
}
AllRoles = RoleManager.Roles.ToList();
var roles = await UserManager.GetRolesAsync(User);
SelectedRole = roles.FirstOrDefault() ?? "-1";
}
}
private async Task SaveChanges()
{
if (User is not null)
{
if (string.IsNullOrEmpty(SelectedRole) || SelectedRole == "-1")
{
var currentRoles = await UserManager.GetRolesAsync(User);
await UserManager.RemoveFromRolesAsync(User, currentRoles);
}
else
{
var currentRoles = await UserManager.GetRolesAsync(User);
var rolesToRemove = currentRoles.Where(r => r != SelectedRole).ToList();
await UserManager.RemoveFromRolesAsync(User, rolesToRemove);
if (!currentRoles.Contains(SelectedRole))
{
await UserManager.AddToRoleAsync(User, SelectedRole);
}
}
}
}
}
What I’ve Tried:
- Verified that the SelectedRole property is a string.
- Confirmed that AllRoles contains the correct data.
- Forced a value to SelectedRole directly before the if condition in the SaveChanges method, and the rest of the program works as expected, meaning the issue is isolated to the InputSelect not updating SelectedRole.
Expected Behavior:
The SelectedRole should update when a new role is selected from the dropdown, and the correct role should be saved when changes are submitted.
Actual Behavior:
The SelectedRole does not reflect the new selection, and the saved role remains as the initially loaded role.
How can I ensure that the InputSelect properly updates the SelectedRole variable?
2
Answers
Based on
I can’t see what’s wrong with your code, but it’s probably in the stuff you haven’t shown. Here’s a stripped down version of your code as a single page that works.
Try to set a break point in the
OnInitializedAsync
method, you will find that after submitting the form, this method will execute first and then theSaveChanges
method, so it will change the selected value to the default value.To solve this issue, you can check whether the
SelectedRole
is null or not in theOnInitializedAsync
method, and then set the default value. Code like this:Besides, since you will receive the data from the form. I think you’d better to add the
[SupplyParameterFromForm]
attribute for theUser
andSelectedRole
, after modified the code should like this:After that in the SaveChanges method, you can see the selected value.