Add message template formatting to DataAnnotations validation attributes - #132764
Conversation
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
Tagging subscribers to this area: @dotnet/area-system-componentmodel-dataannotations |
There was a problem hiding this comment.
Pull request overview
Adds a new public formatting primitive to DataAnnotations validation attributes so callers can supply an external composite-format template while each attribute remains responsible for projecting its own placeholder arguments.
Changes:
- Add
ValidationAttribute.FormatMessage([StringSyntax("CompositeFormat")] string format, string name)and route the baseFormatErrorMessageimplementation through it. - Override
FormatMessagein built-in attributes that require additional placeholders (e.g.,{1},{2}), preserving existing argument ordering andCurrentCultureformatting behavior. - Add/extend tests to cover supplied formats, virtual dispatch, culture-sensitive formatting, and invalid/null formats.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationAttribute.cs | Introduces FormatMessage and updates base FormatErrorMessage to delegate through it. |
| src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/CompareAttribute.cs | Overrides FormatMessage to supply the other-property display name argument. |
| src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/FileExtensionsAttribute.cs | Overrides FormatMessage to supply normalized/dot-prefixed extensions. |
| src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/LengthAttribute.cs | Overrides FormatMessage to supply min/max length placeholders. |
| src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/MaxLengthAttribute.cs | Overrides FormatMessage to supply the max length placeholder. |
| src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/MinLengthAttribute.cs | Overrides FormatMessage to supply the min length placeholder. |
| src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/RangeAttribute.cs | Overrides FormatMessage to supply converted min/max placeholders. |
| src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/RegularExpressionAttribute.cs | Overrides FormatMessage to supply the regex pattern placeholder. |
| src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/StringLengthAttribute.cs | Overrides FormatMessage to supply maximum/minimum length placeholders and keeps default-template selection in FormatErrorMessage. |
| src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs | Updates public surface area (ref) to include the new virtual and related overrides. |
| src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/ValidationAttributeTests.cs | Adds base-level tests for FormatMessage, null/invalid format behavior, and FormatErrorMessage virtual dispatch. |
| src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/CompareAttributeTests.cs | Adds coverage for CompareAttribute.FormatMessage argument projection and display-name behavior. |
| src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/FileExtensionsAttributeTests.cs | Adds coverage for FileExtensionsAttribute.FormatMessage using normalized extensions. |
| src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/LengthAttributeTests.cs | Adds coverage for LengthAttribute.FormatMessage placeholder projection. |
| src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/MaxLengthAttributeTests.cs | Adds coverage for MaxLengthAttribute.FormatMessage placeholder projection. |
| src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/MinLengthAttributeTests.cs | Adds coverage for MinLengthAttribute.FormatMessage placeholder projection. |
| src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/RangeAttributeTests.cs | Adds coverage for RangeAttribute.FormatMessage conversion and culture-sensitive formatting. |
| src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/RegularExpressionAttributeTests.cs | Adds coverage for RegularExpressionAttribute.FormatMessage supplying the pattern. |
| src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/StringLengthAttributeTests.cs | Adds coverage for StringLengthAttribute.FormatMessage placeholder projection and FormatErrorMessage behavior. |
Add the approved ValidationAttribute.FormatMessage API for caller-supplied composite formats and project built-in attribute arguments through overrides. Cover culture, virtual dispatch, error paths, and source/ref naming consistency. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 524df8bb-0555-4425-b73f-bc8340d0dfc2
db016ee to
c3ab07b
Compare
|
Should we also update the validation attribute replicas emitted by |
- Detect FormatMessage support from target compilation symbols - Preserve attribute-specific arguments in generated replicas - Share Range initialization between validation and formatting - Add deterministic baselines and runtime regression coverage Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 524df8bb-0555-4425-b73f-bc8340d0dfc2
6ec2050 to
43ba3c4
Compare
There was a problem hiding this comment.
Looks good.
I don't have a strong opinion about the added argument null checks. They are redundant, but also mean the exception is thrown at the level of the public contract. Considering the existing FormatErrorMessage did not have them, I would probably remove them from FormatMessage too.
Rely on string.Format to validate null format strings, use a valid RangeAttribute in null-format coverage, and update generated baselines. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 524df8bb-0555-4425-b73f-bc8340d0dfc2
|
/ba-g Remaining unclassified failures are the |
|
/backport to release/11.0 |
|
Started backporting to |
Summary
Adds the approved
ValidationAttribute.FormatMessageAPI so callers can supply externally localized composite-format strings while each validation attribute remains responsible for providing its placeholder arguments.Changes
ValidationAttribute.FormatMessage([StringSyntax("CompositeFormat")] string format, string name).FormatErrorMessageimplementation through the new method.CompareAttribute,FileExtensionsAttribute,LengthAttribute,MaxLengthAttribute,MinLengthAttribute,RangeAttribute,RegularExpressionAttribute, andStringLengthAttribute.CurrentCultureformatting.Existing
FormatErrorMessagebehavior remains unchanged.Testing
dotnet build— succeeded with 0 warnings and 0 errors.dotnet build /t:test .\tests\System.ComponentModel.Annotations.Tests.csproj— 1,008 passed, 0 failed, 0 skipped.Fixes #132605
Note
This pull request description was generated with GitHub Copilot.