From ce1d46f797063ef7942d12b4bf02d4c723ecc73f Mon Sep 17 00:00:00 2001 From: Thijs Schreijer | Vcare Date: Tue, 2 Sep 2025 13:07:06 +0200 Subject: [PATCH 1/2] chore(test): add test for duplicate error messages --- tests/MiniValidation.UnitTests/TryValidate.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/MiniValidation.UnitTests/TryValidate.cs b/tests/MiniValidation.UnitTests/TryValidate.cs index 0d59e1e..703a4d0 100644 --- a/tests/MiniValidation.UnitTests/TryValidate.cs +++ b/tests/MiniValidation.UnitTests/TryValidate.cs @@ -464,4 +464,23 @@ public async Task TryValidateAsync_With_Attribute_Attached_Via_TypeDescriptor() Assert.Single(errors["PropertyToBeRequired"]); Assert.Single(errors["AnotherProperty"]); } + + + private class TestResults + { + [MinLength(3)] + public string ErrorCode { get; set; } = string.Empty; + } + + [Fact] + public void MinLengthAttribute_ShouldNotProduceDuplicateErrors() + { + var testObj = new TestResults { ErrorCode = "12" }; + var isValid = MiniValidator.TryValidate(testObj, out var errors); + + Assert.False(isValid); + Assert.True(errors.ContainsKey(nameof(TestResults.ErrorCode))); + var errorMessages = errors[nameof(TestResults.ErrorCode)]; + Assert.Single(errorMessages); + } } From 2223e4b5c7448782de93de2cfad7bf75783f587e Mon Sep 17 00:00:00 2001 From: Thijs Schreijer | Vcare Date: Tue, 2 Sep 2025 13:16:19 +0200 Subject: [PATCH 2/2] fix(msg): remove duplicate messages fixes #79 --- src/MiniValidation/TypeDetailsCache.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/MiniValidation/TypeDetailsCache.cs b/src/MiniValidation/TypeDetailsCache.cs index aee8fb2..737168d 100644 --- a/src/MiniValidation/TypeDetailsCache.cs +++ b/src/MiniValidation/TypeDetailsCache.cs @@ -212,6 +212,15 @@ private static (ValidationAttribute[]?, DisplayAttribute?, SkipRecursionAttribut } } + // Deduplicate validation attributes by type and error message + if (validationAttributes is not null) + { + validationAttributes = validationAttributes + .GroupBy(a => a.GetType().FullName + ":" + a.FormatErrorMessage(property.Name)) + .Select(g => g.First()) + .ToList(); + } + return new(validationAttributes?.ToArray(), displayAttribute, skipRecursionAttribute); }