【问题标题】:ASP.NET Blazor Required Validation with InputSelect使用 InputSelect 进行 ASP.NET Blazor 所需的验证
【发布时间】:2020-11-10 19:50:02
【问题描述】:

我正在尝试让 Required 属性与 InputSelect 一起使用,但验证在 Blazor Server 中不起作用。无需选择即可提交表单。有趣的是,它在模型属性可以为空时起作用。在 .NET 5.0 之前,它不适用于可空类型,因为 InputSelect 不支持它们。然而,我想要一个不可为空的必需属性,因为我想将我的 API 中的 dto 作为模型重用,而且它在逻辑上是错误的。

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; }
}

public enum SomeEnum
{
    A = 1,
    B = 2
}

页面

@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="">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);
    }
}

【问题讨论】:

    标签: c# asp.net blazor blazor-server-side


    【解决方案1】:

    我不确定我是否理解你,但让我们试一试......

    但是我想要一个不可为空的必需属性

    您的意思是,例如,您想要如下属性:

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

    像这样绑定到 InputSelect 组件:

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

    当用户点击“提交”按钮时,如果用户没有选择值,应该显示验证消息?

    如果是,这就是我的答案:

    InputSelect 组件,至少在 .Net 5.0 之前,只能绑定到字符串和枚举类型。

    如果你想让你的 InputSelect 支持绑定到一个 int,就像上面的例子,你应该把它子类化如下......

    public class InputSelectNumber<T> : InputSelect<T>
        {
            
            protected override bool TryParseValueFromString(string value, out T result, out string validationErrorMessage)
            {
                if (typeof(T) == typeof(int))
                {
                    if (int.TryParse(value, out var resultInt))
                    {
                        result = (T)(object)resultInt;
                        validationErrorMessage = null;
                        return true;
                    }
                    else
                    {
                        result = default;
                        validationErrorMessage = "The chosen value is not a valid number.";
                        return false;
                    }
                }
                else
                {
                    return base.TryParseValueFromString(value, out result, out validationErrorMessage);
                }
            }
        }
    

    更新

    我可以绑定它,但它不支持所需的属性,不执行验证

    请运行下面的代码,为名称字段输入一个值,然后按“提交”按钮。表格已“提交”。现在,选择一个国家,然后选择“选择您的国家:”...显示验证消息。 结论:仅当先前选择了一个值然后将其删除时,才会进行验证。这是设计的行为还是错误,我不知道。但是,我认为这种行为与 Blazor 无关。需要检查具有必需属性的选择元素在 Razor 页面中的行为方式。无论如何,我会尝试解决这个错误,如果成功,我会告诉你......

    @using System.ComponentModel.DataAnnotations;
     
    <EditForm EditContext="@EditContext" OnValidSubmit="HandleValidSubmit">
        <DataAnnotationsValidator />
    
        <div class="form-group">
            <label for="name">Enter your Name: </label>
            <InputText Id="name" Class="form-control" @bind-Value="@comment.Name"></InputText>
            <ValidationMessage For="@(() => comment.Name)" />
    
        </div>
        <div class="form-group">
            <label for="body">Select your country: </label>
    
            <InputSelect @bind-Value="@comment.Country" >
                <option value="0">Select country...</option>
                @foreach (var country in Enum.GetValues(typeof(Country)))
                {
                
                    <option value="@country">@country</option>
                }
            </InputSelect>
                   
            <ValidationMessage For="@(() => comment.Country)" />
        </div>
    
        <p>
            <button type="submit">Submit</button>
        </p>
    </EditForm>
    
    
    @code
        {
        private EditContext EditContext;
        private Comment comment = new Comment();
    
        private void HandleValidSubmit()
        {
            Console.WriteLine("Submitting");
        }
        protected override void OnInitialized()
        {
            EditContext = new EditContext(comment);
    
    
            base.OnInitialized();
        }
    
        public enum Country
        {
            USA = 1,
            Britain,
            Germany,
            Israel
    
        }
        public class Comment
        {
            [Required]
            public string Name { get; set; }
            [Required]
            public Country Country { get; set; }
        }
    
    }   
    

    【讨论】:

    • 在 .NET 5 中 InputSelect 确实可以绑定到 int。但是我在 .NET 3.1 中使用枚举绑定 InputSelect 遇到了这个问题。
    • 你的意思是你不能将你的 selectinput 绑定到一个枚举类型?如果是这样,这很奇怪。
    • 我可以绑定它,但它不支持所需的属性,不执行验证
    • 做我自己的研究我得到了几乎相同的观点。我想知道我是否应该提交一个 github bug
    • 是的,您可以在 github 中提交问题,但并不是说这只是枚举类型的问题。例如,如果您使用绑定到字符串类型,如果您未能选择一个值,则只要按下“提交”按钮就会进行验证。
    【解决方案2】:

    一个快速而肮脏的解决方法是在模型中的枚举上使用Range 属性。您必须为您的枚举分配数值并使用基于它们的属性。这绝对不是最好的解决方案,但这对我暂时有用。如果有人找到更好的解决方案,请分享。

    例子:

    public class SomeModel
    {
        [Required]
        public string SomeString { get; set; }
    
        [Required]
        [Range(1, int.MaxValue)]
        public SomeEnum SomeEnum { get; set; }
    
        [Required]
        public SomeEnum? SomeNullableEnum { get; set; }
    
        [Required]
        public int SomeInt { get; set; }
    
        [Required]
        public int? SomeNullableInt { get; set; }
    }
    
    public enum SomeEnum
    {
        A = 1,
        B = 2
    }
    

    【讨论】:

    • 哈,真聪明!
    猜你喜欢
    • 2020-12-26
    • 2018-08-28
    • 2021-02-06
    • 2021-06-20
    • 2020-10-30
    • 2021-06-22
    • 2021-03-06
    • 2023-03-12
    • 2022-08-16
    相关资源
    最近更新 更多