需要演示 DataTypeAttribute 的这种用法(如 Microsoft 教程中所述)

问题描述 投票:0回答:1

我正在从 ASP.NET MVC 迁移到 ASP.NET Core,同时研究此页面上的 Microsoft 文档 https://learn.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/验证?view=aspnetcore-2.2

我读过这行关于

DataTypeAttribute

DataType 属性可以使 ASP.NET Core 框架选择正确的字段模板来呈现数据。 DisplayFormat 如果单独使用,则使用字符串模板。

这对我来说听起来不清楚,我所知道的

DataTypeAttribute
就是上面一行(在同一页上)中提到的内容:

浏览器可以启用 HTML5 功能(例如显示日历控件、适合区域设置的货币符号、电子邮件链接等)

所以这意味着第一个引用确实谈论了与第二个不同的东西。我正在寻求一些更清晰的解释来解释它的含义(在第一个引用中)以及(如果可能的话)一些有趣的代码片段来证明这一点。

更新

更准确地说,我在这里想要什么,实际上是两个引号之间的差异,如以下快照所示:

我理解第一句话(在快照中),但实际上第二句话让我感到困惑,这就是我要求更清晰的解释。这样一个列表中的 2 个点不可能相同,可以吗?

c# asp.net-mvc asp.net-core
1个回答
1
投票

DataType 属性可以使 ASP.NET Core 框架选择正确的字段模板来呈现数据。 DisplayFormat 如果单独使用,则使用字符串模板。

DataType
只不过是描述与数据字段
相关的数据类型的
enum
,例如,
Date
DateTime
Currency
Url
CreditCard
和很快。

[DataTypeAttribute]
只是一个指示符,指示如何生成标签

考虑以下模型:

    [Display(Name = "Release Date"), DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    public DateTime ReleaseDate2 { get; set; 

ReleaseDate
ReleaseDate2
都具有
DateTime
相同的声明类型。但两个字段渲染的html类型不同:

<input class="form-control" type="date" data-val="true" data-val-required="The Release Date field is required." id="ReleaseDate" name="ReleaseDate" value="">

<input class="form-control" type="datetime-local" data-val="true" data-val-required="The ReleaseDate2 field is required." id="ReleaseDate2" name="ReleaseDate2" value="">

请注意,第一个字段是

type="date"
,而第二个字段是
type="datetime-local"
。这是由
TagHelper
自动为您完成的。

此外,如果字段有值,则

TagHelper
在构造
[DateTypeAttribute]
时会知道
ModelExpression
,并在处理此标签时获取此类型的相关格式:

    string format;
    if (string.Equals("month", inputType, StringComparison.OrdinalIgnoreCase))
    {
        // "month" is a new HTML5 input type that only will be rendered in Rfc3339 mode
        format = "{0:yyyy-MM}";
    }
    else if (string.Equals("decimal", inputTypeHint, StringComparison.OrdinalIgnoreCase) &&
        string.Equals("text", inputType, StringComparison.Ordinal) &&
        string.IsNullOrEmpty(modelExplorer.Metadata.EditFormatString))
    {
         // ...
    }
    else if ...

更多详情请参见 GetFormat(modelExplorer, inputTypeHint, inputType)

处理

datetime
&
date
&
time
时,相关格式由以下方式生成:

private static readonly Dictionary<string, string> _rfc3339Formats =
    new Dictionary<string, string>(StringComparer.Ordinal)
    {
        { "date", "{0:yyyy-MM-dd}" },
        { "datetime", @"{0:yyyy-MM-ddTHH\:mm\:ss.fffK}" },
        { "datetime-local", @"{0:yyyy-MM-ddTHH\:mm\:ss.fff}" },
        { "time", @"{0:HH\:mm\:ss.fff}" },
    };

结果,渲染的视图是:

这就是

DateTypeAttribute
影响显示格式的方式。


最后,你可能想知道

data-
属性是如何生成的,你可以看一下
DataTypeAttributeAdapter
的源代码:

    MergeAttribute(context.Attributes, "data-val", "true");
    MergeAttribute(context.Attributes, RuleName, GetErrorMessage(context));

还有:ValidationAttributeAdapterProvider

    ... 
     else if (type == typeof(CreditCardAttribute))
    {
        adapter = new DataTypeAttributeAdapter((DataTypeAttribute)attribute, "data-val-creditcard", stringLocalizer);
    }

    ... 
    else if (type == typeof(EmailAddressAttribute))
    {
        adapter = new DataTypeAttributeAdapter((DataTypeAttribute)attribute, "data-val-email", stringLocalizer);
    }
    else if (type == typeof(PhoneAttribute))
    {
        adapter = new DataTypeAttributeAdapter((DataTypeAttribute)attribute, "data-val-phone", stringLocalizer);
    }
    else if (type == typeof(UrlAttribute))
    {
        adapter = new DataTypeAttributeAdapter((DataTypeAttribute)attribute, "data-val-url", stringLocalizer);
    }
    ...

这意味着在处理

Email
Phone
等时,ASP.NET Core 还将重用
DataTypeAttribute
并为您生成不同的验证元信息(但
DateTypeAttribute
不会验证这些字段)。


[更新]:

也许使用

DataType=Currency
@Hooman Bahreini评论是一个更好的例子。

但是这里渲染的

type
input
不会是
number
,而是一个普通的
text
text
不是 HTML5 功能。另外,我现在将使用
DisplayFor()
作为示例。

考虑以下字段:

    [Column(TypeName = "decimal(10, 4)")]
    public decimal PlainPriceField { get; set; }

    [DataType(DataType.Currency)]
    [Column(TypeName = "decimal(10, 4)")]
    public decimal PriceWithDateType { get; set; }

    [DataType(DataType.Currency)]
    [Column(TypeName = "decimal(10, 4)")]
    [DisplayFormat(DataFormatString = "₿ {0:F3}BTC", ApplyFormatInEditMode = false)]
    public decimal PriceWithDateTypeAndDisplayFormat { get; set; }

默认情况下,数据库将以 2 的比例存储

decimal
。为了清楚地说明这个问题,我添加了
[Column]
注释将它们声明为
decimal(10,4)

然后,我设置了所有价格字段

=1.2345
。请注意,所有这些字段在内存中的值均为
1.2345

但是,当呈现给最终用户时,

@Html.DisplayFor(item=>item.XyzPriceField)
的结果将是:

  • PlainPriceField
    1.23
  • PriceWithDataType
    $1.23
    (而不是
    1.2345
    €1.2345
    或其他任何东西)
  • PriceWithDataTypeAndDisplayFormat
    ₿ 1.235BTC

PriceWithDataType
以前缀
$
呈现,这是由当前区域设置确定的美元符号。

请注意,在这种情况下,HTML5 根本不支持货币(它将呈现为文本)。而且我们没有为此货币字段设置字符串模板。

通过检查

[DataType(DataType.Currency)]
注释,
ASP.NET Core
框架知道这是一个
currency
数字,并且应该以某种特定格式显示。尽管不支持 HTML5 货币,但最终用户将获得
$1.23
上面已经介绍了 ASP.NET Core 如何为某些
DataType
选择内置格式的方式。

最后,如果您同时提供

[DisplayFormat]
,ASP.NET Core 将更喜欢
DataFormatString
中定义的格式。

© www.soinside.com 2019 - 2024. All rights reserved.