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's InputSelect does not validate with Required attribute #52779

Closed jeremysalwen closed 10 months ago

jeremysalwen commented 10 months ago

Is there an existing issue for this?

Describe the bug

When using an required enum property with an input select, the validation is mistakenly not performed:

    [Required]
    public SomeEnum SomeEnum { get; set; }

Will not validate the required value, and instead silently sets it to the invalid enum value 0.

This bug was previously reported but mistakenly closed: Blazor's InputSelect does not validate with Required attribute The bug is still present in .NET 8.

Expected Behavior

I expect the validation to fail since a Required property is not set, i.e. the behavior of any other input element.

Steps To Reproduce

{
    A = 1,
    B = 2
}
public class SomeModel
{
    [Required]
    public string SomeString { get; set; }

    [Required]
    public SomeEnum SomeEnum { get; set; }

    [Required]
    public SomeEnum? SomeNullableEnum { get; set; }

    [Required]
    public int SomeInt { get; set; }

    [Required]
    public int? SomeNullableInt { get; set; }
}
@page "/testrequired"
@using TestNET5BlazorServerApp.Data;

<EditForm Model="Model" OnValidSubmit="Submit">

    <DataAnnotationsValidator />
    <ValidationSummary />

    String:
    <br />
    <InputText @bind-Value="Model.SomeString" />
    <br />
    <br />
    Enum:
    <br />
    <InputSelect @bind-Value="Model.SomeEnum">
        <option value="0">Select Enum</option>
        <option value="@SomeEnum.A">@SomeEnum.A</option>
        <option value="@SomeEnum.B">@SomeEnum.B</option>
    </InputSelect>
    <br />
    <br />

    Nullable Enum:
    <br />
    <InputSelect @bind-Value="Model.SomeNullableEnum">
        <option>Select Nullable Enum</option>
        <option value="@SomeEnum.A">@SomeEnum.A</option>
        <option value="@SomeEnum.B">@SomeEnum.B</option>
    </InputSelect>
    <br />
    <br />

    Int:
    <br />
    <InputSelect @bind-Value="Model.SomeInt">
        <option>Select Int</option>
        <option value="1">1</option>
        <option value="2">2</option>
    </InputSelect>
    <br />
    <br />

    Nullable Int:
    <br />
    <InputSelect @bind-Value="Model.SomeNullableInt">
        <option>Select Nullable Int</option>
        <option value="1">1</option>
        <option value="2">2</option>
    </InputSelect>
    <br />
    <br />

    <button type="submit">Save</button>
</EditForm>

@code 
{
    SomeModel Model = new Data.SomeModel();

    void Submit()
    {
        System.Diagnostics.Debug.WriteLine("Enum " + Model.SomeEnum);
        System.Diagnostics.Debug.WriteLine("Nullable Enum " + Model.SomeNullableEnum);
        System.Diagnostics.Debug.WriteLine("Int " + Model.SomeInt);
        System.Diagnostics.Debug.WriteLine("Nullable Int " + Model.SomeNullableInt);
    }
}

Exceptions (if any)

No response

.NET Version

8.0.100

Anything else?

No response

javiercn commented 10 months ago

@jeremysalwen thanks for contacting us.

Unfortunately, the semantics for the required attribute aren't "this property was set". RequiredAttribute only checks for null values and empty strings if configured to do so.

In your case, you can either use a nullable Enum or create your own validation attribute. In your case, you should use [EnumDataType(typeof(SomeEnum))] to ensure the value was set.

The logic for the required attribute is here. We don't do any processing nor special casing based on it at the Blazor level.

ghost commented 10 months ago

This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes.

See our Issue Management Policies for more information.