具有自定义属性的 ValidationMessage 奇怪行为
ValidationMessage strange behaviour with custom attribute
我在 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 属性 的模型,如果另一个 属性有一定的价值)。
在 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”,然后单击提交,我得到以下结果:
Amount 有效,因为它具有默认值 0,并且 RequiredAttribute 仅检查空值。
NullAmount 无效,它显示在 ValidationSummary 中,输入字段也是红色的,因为它无效,并且还显示验证消息。
Id 无效,因为在 RequiredIf 属性中我检查 int 值是否为 0,它具有默认值 0,错误消息显示在 ValidationSummary 中,有趣的部分来了,输入字段不是红色,验证消息未显示。
Nullable Id 字段也是如此,验证摘要中显示了错误消息,但该字段不是红色,没有显示验证消息。
现在,如果我为 Id 和 NullableId(具有自定义属性的字段)输入有效值,然后我将 Id 更改为 0,将 NullableId 更改为空,则会发生以下情况:
两个输入字段都变为红色,两个属性都显示验证消息,但在验证摘要中,两个错误消息都显示两次。
现在,如果我点击提交,两个输入字段都会变为绿色,验证消息也消失了,但仍会显示在摘要中。
我完全迷路了,不知道是我的自定义验证属性有问题,Blazor 组件有问题,还是未知问题。内置的 Required 属性工作正常,我只是将它添加到代码中以查看我的表单是否适用。
你有什么想法吗?
终于找到问题所在了。在validation属性中,当返回错误结果时,我必须在构造函数中传递memberName。
return new ValidationResult(ErrorMessage, validationContext.MemberName)
非常感谢@petyusa,我也运行 关注这个问题,这让我抓狂。我偶然发现了您的解决方案,它立即解决了。但是,我不得不将一个字符串数组传递给第二个参数(可能是因为我使用的是 .NET 5.0),而不是一个简单的字符串:
return new ValidationResult(ErrorMessage, new []{validationContext.MemberName});
我在 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 属性 的模型,如果另一个 属性有一定的价值)。
在 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”,然后单击提交,我得到以下结果:
Amount 有效,因为它具有默认值 0,并且 RequiredAttribute 仅检查空值。 NullAmount 无效,它显示在 ValidationSummary 中,输入字段也是红色的,因为它无效,并且还显示验证消息。 Id 无效,因为在 RequiredIf 属性中我检查 int 值是否为 0,它具有默认值 0,错误消息显示在 ValidationSummary 中,有趣的部分来了,输入字段不是红色,验证消息未显示。 Nullable Id 字段也是如此,验证摘要中显示了错误消息,但该字段不是红色,没有显示验证消息。
现在,如果我为 Id 和 NullableId(具有自定义属性的字段)输入有效值,然后我将 Id 更改为 0,将 NullableId 更改为空,则会发生以下情况:
两个输入字段都变为红色,两个属性都显示验证消息,但在验证摘要中,两个错误消息都显示两次。
现在,如果我点击提交,两个输入字段都会变为绿色,验证消息也消失了,但仍会显示在摘要中。
我完全迷路了,不知道是我的自定义验证属性有问题,Blazor 组件有问题,还是未知问题。内置的 Required 属性工作正常,我只是将它添加到代码中以查看我的表单是否适用。
你有什么想法吗?
终于找到问题所在了。在validation属性中,当返回错误结果时,我必须在构造函数中传递memberName。
return new ValidationResult(ErrorMessage, validationContext.MemberName)
非常感谢@petyusa,我也运行 关注这个问题,这让我抓狂。我偶然发现了您的解决方案,它立即解决了。但是,我不得不将一个字符串数组传递给第二个参数(可能是因为我使用的是 .NET 5.0),而不是一个简单的字符串:
return new ValidationResult(ErrorMessage, new []{validationContext.MemberName});