Repository navigation
Blazor InputSelect with multiple enabled throws NullRefException if nothing is selected #54431
Copy link
Copy link
Labels
area-blazorIncludes: Blazor, Razor ComponentsIncludes: Blazor, Razor ComponentsbugThis issue describes a behavior which is not expected - a bug.This issue describes a behavior which is not expected - a bug.help wantedUp for grabs. We would accept a PR to help resolve this issueUp for grabs. We would accept a PR to help resolve this issue
Milestone
Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
If there is an InputSelect in an EditForm with multiple values (via array) and nothing is selected (or everything is deselected) the following exception is thrown:
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.AspNetCore.Components.BindConverter.FormatterDelegateCache.<>c__DisplayClass3_0`1.<MakeArrayFormatter>g__FormatArrayValue|0(T[] value, CultureInfo culture)
at Microsoft.AspNetCore.Components.Forms.InputSelect`1.BuildRenderTree(RenderTreeBuilder builder)
at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)
Assuming the following model
{
public List<(bool, string)> CurrentRoles { get; set; } = new List<(bool, string)>();
public string[] SelectedRoles { get; set; } = [];
}And the following markup:
<div class="form-group">
<label for="roles">Roles</label>
<InputSelect id="roles" class="form-control" @bind-Value="Model.SelectedRoles">
@if(Model.CurrentRoles is not null)
{
@foreach (var (selected, role) in Model.CurrentRoles)
{
<option selected="@selected">@role</option>
}
}
</InputSelect>
</div>Repo see below, markup is here: https://github.com/Tornhoof/InputMultiSelectRepro/blob/main/Components/Pages/Home.razor
Expected Behavior
No such exception
Workaround is to set the array to [] in OnInitializedAsync
Steps To Reproduce
- checkout https://github.com/Tornhoof/InputMultiSelectRepro
- make sure line 76 (Model.SelectedRoles ??= []) in Home.razor is commented
- Start project
- Deselect FirstRole in the Input Select Field
Exceptions (if any)
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.AspNetCore.Components.BindConverter.FormatterDelegateCache.<>c__DisplayClass3_0`1.<MakeArrayFormatter>g__FormatArrayValue|0(T[] value, CultureInfo culture)
at Microsoft.AspNetCore.Components.Forms.InputSelect`1.BuildRenderTree(RenderTreeBuilder builder)
at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
at Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(Int32 componentId, RenderFragment renderFragment)
at Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged()
at Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync()
at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
at Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderRootComponentAsync(Int32 componentId, ParameterView initialParameters)
at Microsoft.AspNetCore.Components.HtmlRendering.Infrastructure.StaticHtmlRenderer.BeginRenderingComponent(IComponent component, ParameterView initialParameters)
at Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.RenderEndpointComponent(HttpContext httpContext, Type rootComponentType, ParameterView parameters, Boolean waitForQuiescence)
at Microsoft.AspNetCore.Components.Endpoints.RazorComponentEndpointInvoker.RenderComponentCore(HttpContext context)
at Microsoft.AspNetCore.Components.Endpoints.RazorComponentEndpointInvoker.RenderComponentCore(HttpContext context)
at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.<>c.<<InvokeAsync>b__10_0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Antiforgery.Internal.AntiforgeryMiddleware.InvokeAwaited(HttpContext context)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
.NET Version
8.0.200
Anything else?
No response
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area-blazorIncludes: Blazor, Razor ComponentsIncludes: Blazor, Razor ComponentsbugThis issue describes a behavior which is not expected - a bug.This issue describes a behavior which is not expected - a bug.help wantedUp for grabs. We would accept a PR to help resolve this issueUp for grabs. We would accept a PR to help resolve this issue
Activity
gragra33 commentedon Mar 8, 2024
You may need nullable:
Tornhoof commentedon Mar 8, 2024
Yeah, I tried that, doesn't help, still throws the same exception.
gragra33 commentedon Mar 8, 2024
@Tornhoof The Binding for the
InputSelectwith no items selected is thowing the exception in the internalBindConverterclass. TheMakeArrayFormattermethod is expecting a non-nullable array. You need to add Validation to disallow no selection. You can read more about Validation here: Determine if a form field is validTornhoof commentedon Mar 8, 2024
@gragra33 I'm aware that I can limit the selection to need more than 0 selections, all the examples (and tests afaik) do that. But that kinda defeats the point of it :)
I'm also aware that I can cheat with some empty string value or conceptionally None Item or something similar, but that also defeats the whole point.
I'm also aware that I can cheat with writing my own component, use input with multiple directly or other methods to bypass the issue or some other method.
My workaround, as described above, is a lot cleaner than those though.
There is a lot of strange (atleast for me) documentation around null and model binding, in this case I simply expect, that for an empty selection input, it creates an empty array for the model binding. I personally think, that empty selections were simply missed during development.
Tornhoof commentedon Mar 11, 2024
Note: In my attempts to repro #54432 I found out, that the issue only happens for SSR, as soon as @rendermode InteractiveServer is added the array is not null, but empty.