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

Kyl*_*Mit 2 .net c# validationattribute data-annotations

使用DataTypeAttribute和传入值DataType.Phone以及继承和自动设置的PhoneAttribute之间的区别是什么?DataTypeDataType.Phone

这两个班级有什么区别吗?

class Person {
   [DataType(DataType.PhoneNumber)]
   public string PhoneNumber {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
class Person {
   [Phone]
   public string PhoneNumber {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

Kyl*_*Mit 5

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

继承链如下所示:

Attribute
  ↳ ValidationAttribute
       ↳ DataTypeAttribute
            ↳PhoneAttribute

所以两者都是实例ValidationAttribute,但两者都不提供开箱即用的验证.DataType基类只提供用于分配enum DataType和离开覆盖验证的结构,直到调用者

DataType - 根据文件:

DataTypeAttribute属性应用于数据字段时,必须执行以下操作:

  • 适当时发出验证错误.

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;
    }
 }
Run Code Online (Sandbox Code Playgroud)

旁白:由于您需要覆盖IsValid,我不确定为什么.NET没有标记类和属性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+)?$";
Run Code Online (Sandbox Code Playgroud)

但是,根据此更改说明,在.NET Framework 4.7.2中已被弃用,可能是由于无约束输入的正则表达式最佳实践中存在注入/安全性问题.

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

<add key="dataAnnotations:dataTypeAttribute:disableRegEx" value="false"/>
Run Code Online (Sandbox Code Playgroud)

测试项目包括根据PhoneAttributeTests.cs应该传递/失败的输入的示例,如果您想针对(不推荐的)正则表达式验证引擎测试匹配输入,这里是Regexr页面.


以下是针对不同版本的.NET的源代码和文档的一些链接:

                  | .NET Core         | .NET Core 2.1  |  .NET 4.7.2     | .NET           |
------------------|-------------------|----------------|-----------------|----------------|
DataTypeAttribute | github.com/dotnet | source.dot.net | referencesource | docs.microsoft |
PhoneAttribute    | github.com/dotnet | source.dot.net | referencesource | docs.microsoft |
Run Code Online (Sandbox Code Playgroud)

注意:当前的文档[Phone]错误地说明验证使用正则表达式,自4.7.2+以来或.NET核心中的任何地方都不正确,所以我已提交此PR以更新