diff --git a/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs b/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs index 5333e8be2b4..315a1cb9d58 100644 --- a/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs +++ b/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs @@ -385,10 +385,6 @@ private void ValidateDataAnnotations(object? value, ValidationContext context, L var result = rule.GetValidationResult(value, context); if (result != null && result != ValidationResult.Success) { - // 查找 resource 资源文件中的 ErrorMessage - var ruleNameSpan = rule.GetType().Name.AsSpan(); - var index = ruleNameSpan.IndexOf(attributeSpan, StringComparison.OrdinalIgnoreCase); - var ruleName = ruleNameSpan[..index]; var find = false; if (!string.IsNullOrEmpty(rule.ErrorMessage)) { @@ -400,29 +396,36 @@ private void ValidateDataAnnotations(object? value, ValidationContext context, L } } - // 通过设置 ErrorMessage 检索 - if (!context.ObjectType.Assembly.IsDynamic && !find - && !string.IsNullOrEmpty(rule.ErrorMessage) - && LocalizerFactory.Create(context.ObjectType).TryGetLocalizerString(rule.ErrorMessage, out var msg)) + if (!context.ObjectType.Assembly.IsDynamic) { - rule.ErrorMessage = msg; - find = true; - } + if (!find && !string.IsNullOrEmpty(rule.ErrorMessage) + && LocalizerFactory.Create(context.ObjectType).TryGetLocalizerString(rule.ErrorMessage, out var msg)) + { + // 通过设置 ErrorMessage 检索 + rule.ErrorMessage = msg; + find = true; + } - // 通过 Attribute 检索 - if (!rule.GetType().Assembly.IsDynamic && !find - && LocalizerFactory.Create(rule.GetType()).TryGetLocalizerString(nameof(rule.ErrorMessage), out msg)) - { - rule.ErrorMessage = msg; - find = true; - } + if (!find && LocalizerFactory.Create(rule.GetType()).TryGetLocalizerString(nameof(rule.ErrorMessage), out msg)) + { + // 通过 Attribute 检索 + rule.ErrorMessage = msg; + find = true; + } - // 通过 字段.规则名称 检索 - if (!context.ObjectType.Assembly.IsDynamic && !find - && LocalizerFactory.Create(context.ObjectType).TryGetLocalizerString($"{memberName}.{ruleName.ToString()}", out msg)) - { - rule.ErrorMessage = msg; - find = true; + if (!find) + { + // 通过 字段.规则名称 检索 + // 查找 resource 资源文件中的 ErrorMessage + var ruleNameSpan = rule.GetType().Name.AsSpan(); + var index = ruleNameSpan.IndexOf(attributeSpan, StringComparison.OrdinalIgnoreCase); + var ruleName = index == -1 ? ruleNameSpan[..] : ruleNameSpan[..index]; + if (LocalizerFactory.Create(context.ObjectType).TryGetLocalizerString($"{memberName}.{ruleName.ToString()}", out msg)) + { + rule.ErrorMessage = msg; + find = true; + } + } } if (!find) diff --git a/test/UnitTest/Components/ValidateFormTest.cs b/test/UnitTest/Components/ValidateFormTest.cs index 06ab0abf5cc..806b13d5400 100644 --- a/test/UnitTest/Components/ValidateFormTest.cs +++ b/test/UnitTest/Components/ValidateFormTest.cs @@ -566,6 +566,27 @@ public async Task Validate_Service_Ok() var msg = cut.FindComponent>().Instance.GetErrorMessage(); Assert.Equal(HasServiceAttribute.Success, msg); } + + [Fact] + public async Task TestService_Ok() + { + // 自定义验证规则没有使用约定 Attribute 结尾单元测试 + var foo = new HasService(); + var cut = Context.RenderComponent(pb => + { + pb.Add(a => a.Model, foo); + pb.AddChildContent>(pb => + { + pb.Add(a => a.Value, foo.Tag2); + pb.Add(a => a.ValueExpression, Utility.GenerateValueExpression(foo, "Tag2", typeof(string))); + pb.Add(a => a.ValidateRules, [new FormItemValidator(new TestValidateRule())]); + }); + }); + var form = cut.Find("form"); + await cut.InvokeAsync(() => form.Submit()); + var msg = cut.FindComponent>().Instance.GetErrorMessage(); + Assert.Equal("Test", msg); + } [Fact] public async Task RequiredValidator_Ok() @@ -726,7 +747,7 @@ public void ShowAllInvalidResult_Ok() private class HasServiceAttribute : ValidationAttribute { public const string Success = "Has Service"; - public const string Error = "No Service"; + private const string Error = "No Service"; protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) { @@ -738,10 +759,21 @@ private class HasServiceAttribute : ValidationAttribute } } + private class TestValidateRule : ValidationAttribute + { + protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) + { + return new("Test"); + } + } + private class HasService { [HasService] public string? Tag { get; set; } + + [TestValidateRule] + public string? Tag2 { get; set; } } [MetadataType(typeof(DummyMetadata))]