Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
I have a simple page to manipulate access of an employee in a Blazor WASM application:
@page "/Admin/AccessControl"
@attribute [Authorize(Roles = "Admin_ConfigAppUserGroups")]
@using SharedLib.Models
@inject IAdminClient _admin
@inject ISystemClient _system
@inject IToastService _toast
<EditForm Model="newAppUserGroup" OnSubmit="HandleSubmit">
<fieldset class="form-group" disabled="@isFormDisabled">
<label class="font-weight-bold" for="users">User</label>
<select class="form-control" id="users" @onchange="HandleSelectUser"
value="@newAppUserGroup.UserId.ToString()">
@if (employees is not null)
{
foreach (var employee in employees)
{
<option value="@employee.EmployeeId.ToString()">@employee.FullnameAndCode</option>
}
}
</select>
</fieldset>
<fieldset class="form-group" disabled="@isFormDisabled">
<label class="font-weight-bold" for="applications">Application</label>
<select class="form-control"
value="@newAppUserGroup.ApplicationId.ToString()"
@onchange="HandleSelectApplication"
id="applications"
required>
@if (applications is not null)
{
foreach (var app in applications)
{
<option value="@app.ApplicationId.ToString()">@app.ApplicationName</option>
}
}
</select>
</fieldset>
<fieldset class="form-group" disabled="@isFormDisabled">
<label class="font-weight-bold" for="appGroups">AppGroups</label>
<InputSelectNumber class="form-control" id="appGroups"
@bind-Value="newAppUserGroup.AppGroupId">
<option value="0">-- No access --</option>
@if (appGroups is not null)
{
foreach (var appGroup in appGroups)
{
<option value="@appGroup.AppGroupId">@appGroup.GroupName</option>
}
}
</InputSelectNumber>
</fieldset>
<input class="btn btn-primary" type="submit" value="Submit" disabled="@isFormDisabled" />
</EditForm>
@code {
private bool isFormDisabled;
private AppUserGroupModel newAppUserGroup = new();
private IEnumerable<EmployeeListItemModel> employees;
private IEnumerable<ApplicationModel> applications;
private IEnumerable<AppGroupListItemModel> appGroups;
protected override async Task OnInitializedAsync()
{
isFormDisabled = true;
await LoadInitialData();
isFormDisabled = false;
}
private async Task LoadAppGroups()
{
appGroups = await _admin.AppGroups_GetAllAsync(newAppUserGroup.ApplicationId);
var desiredGroup = (await _admin.AppUserGroups_GetAllAsync(newAppUserGroup.UserId)).FirstOrDefault(g => g.UserId == newAppUserGroup.UserId && g.ApplicationId == newAppUserGroup.ApplicationId);
newAppUserGroup.AppGroupId = desiredGroup is null ? 0 : desiredGroup.AppGroupId;
}
private async Task LoadInitialData()
{
var employeesTask = _admin.Employees_GetAllAsync(Systems.Shared.Enums.AdminSchema.EmployeeFilter.All);
var applicationsTask = _system.Applications_GetAllAsync();
employees = await employeesTask;
applications = await applicationsTask;
newAppUserGroup.UserId = employees.FirstOrDefault().EmployeeId;
newAppUserGroup.ApplicationId = applications.FirstOrDefault().ApplicationId;
await LoadAppGroups();
}
private async Task HandleSelectUser(ChangeEventArgs args)
{
isFormDisabled = true;
newAppUserGroup.UserId = int.Parse(args.Value.ToString());
await LoadAppGroups();
isFormDisabled = false;
}
private async Task HandleSelectApplication(ChangeEventArgs args)
{
isFormDisabled = true;
newAppUserGroup.ApplicationId = int.Parse(args.Value.ToString());
await LoadAppGroups();
isFormDisabled = false;
}
private async Task HandleSubmit()
{
isFormDisabled = true;
// handle submit logic here
isFormDisabled = false;
}
}
It has been working fine for almost a year.
The IAdminClient and ISystemsClient are abstractions for HTTP requests.
The implementations are as below:
public Task<IEnumerable<ApplicationModel>> Applications_GetAllAsync()
{
return _http.GetFromJsonAsync<IEnumerable<ApplicationModel>>("api/Applications");
}
public Task<IEnumerable<EmployeeListItemModel>> Employees_GetAllAsync(EmployeeFilter filter)
{
return _http.GetFromJsonAsync<IEnumerable<EmployeeListItemModel>>($"api/Employees?filter={(int)filter}");
}
public Task<IEnumerable<AppGroupListItemModel>> AppGroups_GetAllAsync(int applicationId)
{
return _http.GetFromJsonAsync<IEnumerable<AppGroupListItemModel>>($"api/AppGroups?applicationId={applicationId}");
}
public Task<IEnumerable<AppUserGroupModel>> AppUserGroups_GetAllAsync(int userId)
{
return _http.GetFromJsonAsync<IEnumerable<AppUserGroupModel>>($"api/AppUserGroups?userId={userId}");
}
Now, the page does not load, giving error:
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Arg_IndexOutOfRangeException
System.IndexOutOfRangeException: Arg_IndexOutOfRangeException
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendAttributeDiffEntriesForRange(DiffContext& , Int32 , Int32 , Int32 , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence(DiffContext& , Int32 , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& , Int32 , Int32 , Int32 , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence(DiffContext& , Int32 , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& , Int32 , Int32 , Int32 , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer , RenderBatchBuilder , Int32 , ArrayRange`1 , ArrayRange`1 )
at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder , RenderFragment , Exception& )
at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry )
at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
Expected Behavior
The expected behaviour is that page should load properly.
It has been working as expected for the last 10 months.
The number of 'Applications' and 'AppGroups' has remained the same over this period.
Recently, the number of employees increased to 156 and we started facing this issue.
I manually updated logic in API to return 155, 157, and 158 employees and the page works as expected.
But it seems that there is some issue when the count is 156.
Steps To Reproduce
The bug is reproducible as the page does not load when Employees_GetAllAsync(EmployeeFilter filter)
returns 156 items.
But I cannot isolate the issue, as the there are other pages as well having similar Employee dropdown and they are working fine.
Exceptions (if any)
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Arg_IndexOutOfRangeException
System.IndexOutOfRangeException: Arg_IndexOutOfRangeException
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendAttributeDiffEntriesForRange(DiffContext& , Int32 , Int32 , Int32 , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence(DiffContext& , Int32 , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& , Int32 , Int32 , Int32 , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence(DiffContext& , Int32 , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& , Int32 , Int32 , Int32 , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer , RenderBatchBuilder , Int32 , ArrayRange`1 , ArrayRange`1 )
at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder , RenderFragment , Exception& )
at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry )
at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
.NET Version
6.0
Anything else?
No response