dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.36k stars 9.99k forks source link

Blazor - InputSelect prevents form submit when bound to nullable Enum #16768

Closed witoldlitwin closed 4 years ago

witoldlitwin commented 4 years ago

When Blazor's InputSelect is bound to a nullable Enum it prevents the form from being submitted.

There are two console errors:

  1. When selecting a non-default value:
    blazor.server.js:15 [2019-11-02T09:18:27.838Z] Error: There was an unhandled exception on the current circuit, so this circuit will be terminated. For more details turn on detailed exceptions in 'CircuitOptions.DetailedErrors'.
  2. When submitting the form after the non-default value was selected:
    blazor.server.js:1 Uncaught (in promise) Error: Cannot send data if the connection is not in the 'Connected' State.
    at e.send (blazor.server.js:1)
    at e.sendMessage (blazor.server.js:1)
    at e.sendWithProtocol (blazor.server.js:1)
    at e.send (blazor.server.js:1)
    at blazor.server.js:8
    at Object.t.dispatchEvent (blazor.server.js:8)
    at blazor.server.js:8
    at e.onEvent (blazor.server.js:8)
    at e.onGlobalEvent (blazor.server.js:8)

Steps to reproduce:

  1. Add an enum:
    public enum Unit
    {
        Days,
        Hours,
        Months
    }
  2. Add a class with a property of the enum's type and make it nullable:
    public class TestTask
    {
        public Unit? TaskUnit { get; set; }
    }
  3. Add a form and backend code:

    
    <EditForm Model="@taskModel">    
    <InputSelect @bind-Value="@taskModel.TaskUnit" id="dueUnit" class="form-control">
        <option value="@Unit.Days">Days</option>
        <option value="@Unit.Hours">Hours</option>
        <option value="@Unit.Months">Months</option>
    </InputSelect>
    
    <button @onclick="@(() => SaveTask())" class="btn btn-primary">Submit</button>
    </EditForm>

@code { protected Data.TestTask taskModel = new Data.TestTask();

protected void SaveTask()
{
    var model = taskModel;
}

}


4. Run the app, select a non-default value from the dropdown and click the Submit button.

**Expected behaviour:**
No errors in the console, the form can be submitted.
javiercn commented 4 years ago

@witoldlitwin thanks for contacting us.

This seems to be a bug. On submit the current exception is thrown

warn: Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer[100]
      Unhandled exception rendering component: Microsoft.AspNetCore.Components.Forms.InputSelect`1[System.Nullable`1[BlazorServerIndividualSqlLite.Pages.Index+Unit]] does not support the type 'System.Nullable`1[BlazorServerIndividualSqlLite.Pages.Index+Unit]'.
System.InvalidOperationException: Microsoft.AspNetCore.Components.Forms.InputSelect`1[System.Nullable`1[BlazorServerIndividualSqlLite.Pages.Index+Unit]] does not support the type 'System.Nullable`1[BlazorServerIndividualSqlLite.Pages.Index+Unit]'.
   at Microsoft.AspNetCore.Components.Forms.InputSelect`1.TryParseValueFromString(String value, TValue& result, String& validationErrorMessage)
   at Microsoft.AspNetCore.Components.Forms.InputBase`1.set_CurrentValueAsString(String value)
   at Microsoft.AspNetCore.Components.Forms.InputSelect`1.<BuildRenderTree>b__4_0(String __value)
   at Microsoft.AspNetCore.Components.EventCallbackFactoryBinderExtensions.<>c__DisplayClass22_0`1.<CreateBinderCore>b__0(ChangeEventArgs e)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)
fail: Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost[111]
      Unhandled exception in circuit 'Zt7CuYHeXPRxUhRSZEELfB9ujO3ZWDVM90UD_prDExM'.
System.InvalidOperationException: Microsoft.AspNetCore.Components.Forms.InputSelect`1[System.Nullable`1[BlazorServerIndividualSqlLite.Pages.Index+Unit]] does not support the type 'System.Nullable`1[BlazorServerIndividualSqlLite.Pages.Index+Unit]'.
   at Microsoft.AspNetCore.Components.Forms.InputSelect`1.TryParseValueFromString(String value, TValue& result, String& validationErrorMessage)
   at Microsoft.AspNetCore.Components.Forms.InputBase`1.set_CurrentValueAsString(String value)
   at Microsoft.AspNetCore.Components.Forms.InputSelect`1.<BuildRenderTree>b__4_0(String __value)
   at Microsoft.AspNetCore.Components.EventCallbackFactoryBinderExtensions.<>c__DisplayClass22_0`1.<CreateBinderCore>b__0(ChangeEventArgs e)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Components.Forms.InputSelect`1.TryParseValueFromString(String value, TValue& result, String& validationErrorMessage)
   at Microsoft.AspNetCore.Components.Forms.InputBase`1.set_CurrentValueAsString(String value)

The fix likely involves a fix in InputBase.TryParseValueFromString to correctly parse enum values.

javiercn commented 4 years ago

This is a dupe of #13624