DataType(DataType.PhoneNumber) 和 PhoneAttribute 之间有什么区别

What's the difference between DataType(DataType.PhoneNumber) & PhoneAttribute

使用继承DataType和自动设置DataType.PhoneDataType Attribute and passing in a value of DataType.Phone and the Phone Attribute有什么区别?

这两个class有区别吗?

class人{
   <b>[数据类型(DataType.PhoneNumber)]</b>
   public 字符串 Phone 数字 {get;set;}
}
class人{
   <b>[Phone]</b>
   public 字符串 Phone 数字 {get;set;}
}

TLDR[Phone] 提供验证逻辑,而 [DataType] 不提供

继承链如下所示:

Attribute
ValidationAttribute
DataTypeAttribute
PhoneAttribute

所以两者都是 ValidationAttribute 的实例,但是两者都不提供开箱即用的验证。 DataType 基础 class 仅提供用于分配 enum DataType 的结构,并将覆盖验证留给调用者

DataType - 根据文档:

When you apply the DataTypeAttribute attribute to a data field you must do the following:

  • Issue validation errors as appropriate.

DataType - 根据源代码:

[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;
    }
 }

旁白:由于您需要覆盖IsValid,我不确定为什么.NET 没有标记class 和属性 作为 abstract 以保证以编程方式实现。

PhoneAttribute - 验证逻辑

因此,如果您确实想提供验证,并且您使用的是 .NET 4.5+ 或 .NET Core,则可以使用 [Phone] 属性,但验证机制也随着时间的推移而发生变化并且对于什么构成业务流程的有效输入,您可能有一套不同的规则。

.NET Framework 最初使用以下正则表达式:

const string pattern = @"^(\+\s?)?((?<!\+.*)\(\+?\d+([\s\-\.]?\d+)?\)|\d+)([\s\-\.]?(\(\d+([\s\-\.]?\d+)?\)|\d+))*(\s?(x|ext\.?)\s?\d+)?$";

但这在 .NET Framework 4.7.2 中已弃用,根据 this change description, likely due to injection/security concerns layed out in the Regular Expression Best Practices 来自不受约束的输入。

如果您想继续使用正则表达式验证,则必须在 .config 文件的 configuration > appsettings 部分中设置以下内容:

<add key="dataAnnotations:dataTypeAttribute:disableRegEx" value="false"/>
        

如果您想针对(已弃用的)正则表达式验证引擎测试匹配输入,则测试项目包含根据 PhoneAttributeTests.cs and here's a Regexr page 应该 pass/fail 的输入示例。


以下是不同 .NET 风格的源代码和文档的一些链接:

 | .NET 内核 | .NET 核心 2.1 | .NET 4.7.2 |网络 |
------------------|--------------------|------------ -----|----------------|----------------|
<b>数据类型属性</b> | <a href="https://github.com/dotnet/corefx/blob/v2.1.5/src/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/DataTypeAttribute.cs" rel="noreferrer">github.com/dotnet</a> | <a href="https://source.dot.net/#System.ComponentModel.Annotations/System/ComponentModel/DataAnnotations/DataTypeAttribute.cs" rel="noreferrer">source.dot.net</a> | <a href="https://referencesource.microsoft.com/#System.ComponentModel.DataAnnotations/DataAnnotations/DataTypeAttribute.cs" rel="noreferrer">referencesource</a> | <a href="https://docs.microsoft.com/en-us/dotnet/api/System.ComponentModel.DataAnnotations.DataTypeAttribute" rel="noreferrer">docs.microsoft</a> |
<b>电话属性</b> | <a href="https://github.com/dotnet/corefx/blob/v2.1.5/src/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/PhoneAttribute.cs" rel="noreferrer">github.com/dotnet</a> | <a href="https://source.dot.net/#System.ComponentModel.Annotations/System/ComponentModel/DataAnnotations/PhoneAttribute.cs" rel="noreferrer">source.dot.net</a> | <a href="https://referencesource.microsoft.com/#System.ComponentModel.DataAnnotations/DataAnnotations/PhoneAttribute.cs" rel="noreferrer">referencesource</a> | <a href="https://docs.microsoft.com/en-us/dotnet/api/System.ComponentModel.DataAnnotations.PhoneAttribute" rel="noreferrer">docs.microsoft</a> |

注意[Phone] 的当前文档错误地指出验证使用正则表达式,自 4.7.2+ 或 .NET 中的任何地方以来都不是这样核心,所以我 submitted this PR to update