dotnet / dotnet/linker

Support System.ComponentModel.DataAnnotations.ValidationAttribute derived attribute usage

Open
#1,126 1 comment 0 reactions 0 assignees View on GitHub
area-Linker: Steps
Dominant language
C#
Stars
392
Forks
128
Avg merge
2d 10h
Merged PRs (30d)
2

Description

`ComponentModel.DataAnnotations` uses attributes to mark properties with validation behavior. For example, if I have the following program:

```C#
using System.ComponentModel.DataAnnotations;

class Program
{
static void Main(string[] args)
{
var poco = new Poco()
{
Name = "User",
Email = "blah",
};

List results = new List();
Validator.TryValidateObject(poco, new ValidationContext(poco), results, validateAllProperties: true);
Console.WriteLine(results.Count);
}
}

public class Poco
{
[Display]
public string Name { get; set; }
[EmailAddress(ErrorMessageResourceType = typeof(Strings), ErrorMessageResourceName = nameof(Strings.BadEmail))]
public string Email { get; set; }
}
```

It will print out that there is a validation error because `blah` is not a valid email address.

However, when I link this application with `--used-attrs-only true`, the `EmailAddress` attribute is getting stripped from the program. This is because the way `Validator.TryValidateObject` tries getting the attributes is not recognized by the linker.

First, it calls [CustomAttributeExtensions.GetCustomAttributes](https://github.com/dotnet/runtime/blob/4f9ae42d861fcb4be2fcd5d3d55d5f227d30e723/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationAttributeStore.cs#L219-L225) on each property on the object. Then it passes those attributes to a method that filters them to just the [`attributes.OfType()`](https://github.com/dotnet/runtime/blob/4f9ae42d861fcb4be2fcd5d3d55d5f227d30e723/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationAttributeStore.cs#L154-L156).

Possible ways to support this pattern that I can think of:

1. By seeing that `ValidationAttribute` is not sealed, and keeping any attribute that is derived from it since we are looking at `attributes.OfType()`.
2. By adding a mechanism inside of `Validator.TryValidateObject` that says "when an app calls this method, preserve any attributes derived from `ValidationAttribute`".
- Note: this isn't as simple as `PreserveDependency`, because a 3rd party can write a `ValidationAttribute`, and `Validator` won't be able to know about it.

cc @vitek-karas

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.