TLDR: [Phone]
provides validation logic while [DataType]
does not
The inheritance chain looks like this:
Attribute
↳ ValidationAttribute
↳ DataTypeAttribute
↳ PhoneAttribute
So both are instances of ValidationAttribute
, however both don't provide Validation out of the box. The DataType base class just provides the structure for assigning an enum DataType
and leaves overriding the validation up to the caller
DataType
- According to the Docs:
When you apply the DataTypeAttribute
attribute to a data field you must do the following:
- Issue validation errors as appropriate.
DataType
- According to the Source Code:
<!-- language: lang-cs -->
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Parameter, AllowMultiple = false)]
public class DataTypeAttribute : ValidationAttribute
{
/// <summary> Override of <see cref="ValidationAttribute.IsValid(object)" /> </summary>
/// <remarks>This override always returns <c>true</c>. Subclasses should override this to provide the correct result.</remarks>
/// <param name="value">The value to validate</param>
/// <returns>Unconditionally returns <c>true</c></returns>
/// <exception cref="InvalidOperationException"> is thrown if the current attribute is ill-formed.</exception>
public override bool IsValid(object value)
{
EnsureValidDataType();
return true;
}
}
Aside: Since you are required to override IsValid
, I'm not sure why .NET didn't mark the class and property as abstract
to guarantee an implementation programmatically.
PhoneAttribute
- Validation Logic
So if you do want to provide validation, and you're using .NET 4.5+ or .NET Core, you can use the [Phone]
attribute, but the mechanism for validation has changed over time as well and also you might have a different set of rules on what constitutes valid input for your business process.
.NET Framework initially used the following regular expression:
<!-- language: lang-cs -->
const string pattern = @"^(\+\s?)?((?<!\+.*)\(\+?\d+([\s\-\.]?\d+)?\)|\d+)([\s\-\.]?(\(\d+([\s\-\.]?\d+)?\)|\d+))*(\s?(x|ext\.?)\s?\d+)?$";
But this was deprecated in .NET Framework 4.7.2 per this change description, likely due to injection/security concerns layed out in the Regular Expression Best Practices from unconstrained input.
If you want to continue using regex validation, you'd have to set the following in the configuration
> appsettings
section of your .config
file:
<!-- language: lang-xml -->
<add key="dataAnnotations:dataTypeAttribute:disableRegEx" value="false"/>
The Test project includes a sample of what inputs should pass/fail according to PhoneAttributeTests.cs and here's a Regexr page if you want to test out matching input against the (deprecated) regular expression validation engine.
Here's some links for source code and documentation for different flavors of .NET:
<!-- language: lang-none -->
<pre><code> | .NET Core | .NET Core 2.1 | .NET 4.7.2 | .NET |
------------------|-------------------|----------------|-----------------|----------------|
<b>DataTypeAttribute</b> | <a href="https://github.com/dotnet/corefx/blob/v2.1.5/src/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/DataTypeAttribute.cs">github.com/dotnet</a> | <a href="https://source.dot.net/#System.ComponentModel.Annotations/System/ComponentModel/DataAnnotations/DataTypeAttribute.cs">source.dot.net</a> | <a href="https://referencesource.microsoft.com/#System.ComponentModel.DataAnnotations/DataAnnotations/DataTypeAttribute.cs">referencesource</a> | <a href="https://learn.microsoft.com/en-us/dotnet/api/System.ComponentModel.DataAnnotations.DataTypeAttribute">docs.microsoft</a> |
<b>PhoneAttribute</b> | <a href="https://github.com/dotnet/corefx/blob/v2.1.5/src/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/PhoneAttribute.cs">github.com/dotnet</a> | <a href="https://source.dot.net/#System.ComponentModel.Annotations/System/ComponentModel/DataAnnotations/PhoneAttribute.cs">source.dot.net</a> | <a href="https://referencesource.microsoft.com/#System.ComponentModel.DataAnnotations/DataAnnotations/PhoneAttribute.cs">referencesource</a> | <a href="https://learn.microsoft.com/en-us/dotnet/api/System.ComponentModel.DataAnnotations.PhoneAttribute">docs.microsoft</a> |
</code></pre>
Note: The current docs for [Phone]
mistakenly remarks that the validation uses Regular Expressions, which has not been true since 4.7.2+ or anywhere in .NET core, so I've submitted this PR to update