From 1c2f3e01290604fd53d2a4b36c70e755dfa409e4 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 29 Mar 2025 18:16:11 +0800 Subject: [PATCH 1/3] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E6=8F=90=E9=AB=98=E4=BB=A3=E7=A0=81=E5=8F=AF=E8=AF=BB?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ValidateForm/ValidateForm.razor.cs | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs b/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs index 5333e8be2b4..4aa398b9214 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 = ruleNameSpan[..index]; + if (LocalizerFactory.Create(context.ObjectType).TryGetLocalizerString($"{memberName}.{ruleName.ToString()}", out msg)) + { + rule.ErrorMessage = msg; + find = true; + } + } } if (!find) From fad547dfae855165160054ae4df7f4645cc7ac90 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 31 Mar 2025 13:04:56 +0800 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20=E5=85=BC=E5=AE=B9=E9=9D=9E=20A?= =?UTF-8?q?ttribute=20=E7=BB=93=E5=B0=BE=E7=9A=84=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/ValidateForm/ValidateForm.razor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs b/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs index 4aa398b9214..315a1cb9d58 100644 --- a/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs +++ b/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs @@ -419,7 +419,7 @@ private void ValidateDataAnnotations(object? value, ValidationContext context, L // 查找 resource 资源文件中的 ErrorMessage var ruleNameSpan = rule.GetType().Name.AsSpan(); var index = ruleNameSpan.IndexOf(attributeSpan, StringComparison.OrdinalIgnoreCase); - var ruleName = ruleNameSpan[..index]; + var ruleName = index == -1 ? ruleNameSpan[..] : ruleNameSpan[..index]; if (LocalizerFactory.Create(context.ObjectType).TryGetLocalizerString($"{memberName}.{ruleName.ToString()}", out msg)) { rule.ErrorMessage = msg; From 356c9bc79ca567ff37e941df21d6c437f25099b3 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 31 Mar 2025 13:05:06 +0800 Subject: [PATCH 3/3] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTest/Components/ValidateFormTest.cs | 34 +++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) 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))]