ValidationMessage具有自定义属性的奇怪行为

时间:2020-07-21 19:34:09

标签: validation blazor data-annotations blazor-webassembly

我在Blazor应用中显示验证消息时遇到问题。

我有以下模型(用于测试):

public class MyModel
{
    [Required(ErrorMessage = "Amount is required")]
    public int Amount { get; set; }

    [Required(ErrorMessage = "NullableAmount is required")]
    public int? NullableAmount { get; set; }

    [RequiredIf(nameof(Foo), new[] { "bar" }, ErrorMessage = "Id is required")]
    public int Id { get; set; }

    [RequiredIf(nameof(Foo), new[] { "bar" }, ErrorMessage = "NullableId is required")]
    public int? NullableId { get; set; }

    public string Foo { get; set; }
}

我用内置的RequiredAttribute装饰了这些属性,并创建了一个自定义的RequiredIfAttribute,这是该代码:

public class RequiredIfAttribute : ValidationAttribute
{
    private readonly string _otherPropertyName;
    private readonly string[] _otherPropertyValues;

    public RequiredIfAttribute(string otherPropertyName, string[] otherPropertyValues)
    {
        _otherPropertyName = otherPropertyName;
        _otherPropertyValues = otherPropertyValues;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var instance = validationContext.ObjectInstance;
        var type = instance.GetType();
        var propertyValue = type.GetProperty(_otherPropertyName)?.GetValue(instance);

        if (!_otherPropertyValues.Contains(propertyValue?.ToString()))
        {
            return ValidationResult.Success;
        }

        if(value == null)
        {
            return new ValidationResult(ErrorMessage);
        }

        if(int.TryParse(value.ToString(), out var intValue))
        {
            if(intValue == 0)
            {
                return new ValidationResult(ErrorMessage);
            }
        }

        return ValidationResult.Success;
    }
}

我获取另一个属性的名称,该属性的值,并且如果该另一个属性的值与指定的值之一匹配,它将检查用RequiredIf装饰的属性是否为null,或者是否为整数,0。(我将其用于具有可为null的int属性的模型,该属性不能为null或如果其他属性具有特定值则为0。)

在WebAPI方面,它可以正常工作,但是以Blazor形式存在一些问题。这是我的表格:

<EditForm Model="MyModel" OnValidSubmit="OnSubmit">
    <div style="display: flex; flex-direction: column; width: 300px;">
        <DataAnnotationsValidator />
        <ValidationSummary />

        <label>
            Foo:
            <InputText @bind-Value="MyModel.Foo" />
        </label>
        <ValidationMessage For="@(() => MyModel.Foo)" />

        <label>
            Amount:
            <InputNumber @bind-Value="MyModel.Amount" />
        </label>
        <ValidationMessage For="@(() => MyModel.Amount)" />

        <label>
            Null Amount:
            <InputNumber @bind-Value="MyModel.NullableAmount" />
        </label>
        <ValidationMessage For="@(() => MyModel.NullableAmount)" />

        <label>
            Id:
            <InputNumber @bind-Value="MyModel.Id" />
        </label>
        <ValidationMessage For="@(() => MyModel.Id)" />

        <label>
            Null Id:
            <InputNumber @bind-Value="MyModel.NullableId" />
        </label>
        <ValidationMessage For="@(() => MyModel.NullableId)" />

        <button type="submit">submit</button>
    </div>



</EditForm>

我打开表单,为Foo输入值“ bar”,然后单击“提交”,得到以下结果: validation-result after submit button clicked

Amount有效,因为它的默认值为0,而RequiredAttribute仅检查null。 NullAmount无效,它显示在ValidationSummary中,输入字段也是红色,因为它无效,并且还显示验证消息。 id无效,例如在RequiredIf属性中,我将int值与0进行了比较,它具有默认的0值,错误消息显示在ValidationSummary中,并且有趣的部分出现了,输入字段不是红色,并且出现了验证消息没有显示。 同样适用于Nullable Id字段,错误消息显示在验证摘要中,但该字段不是红色,并且不显示验证消息。

现在,如果我输入Id和NullableId(具有我的自定义属性的字段)的有效值,然后将Id更改为0,将NullableId更改为空,则会发生以下情况:

validation-result after changing values

两个输入字段都变为红色,两个属性均显示验证消息,但在验证摘要中,两个错误消息均显示两次。

现在,如果我单击“提交”,则两个输入字段都变为绿色,并且验证消息消失了,但仍显示在摘要中。

value after submitting again

我完全迷路了,不知道我的自定义验证属性是否有问题,Blazor组件中的问题还是未知的问题。内置的Required属性可以正常工作,我只是将其添加到代码中,以查看我的表单是否可以使用它。

你有什么主意吗?

2 个答案:

答案 0 :(得分:0)

我终于找到了问题。在验证属性中,当返回错误结果时,我必须在构造函数中传递memberName。

return new ValidationResult(ErrorMessage, validationContext.MemberName)

答案 1 :(得分:0)

非常感谢@petyusa,我也遇到了这个问题,这让我发疯了。我偶然发现了你的解决方案,它立即解决了它。但是,我必须将一个字符串数组传递给第二个参数(可能是因为我使用的是 .NET 5.0)而不是一个简单的字符串:

return new ValidationResult(ErrorMessage, new []{validationContext.MemberName});
相关问题