Атрибут 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
не проверяет эти поля).
[Update]
Возможно, используя DataType=Currency
, как прокомментировал @ Hooman Bahreini - лучший пример.
Но здесь визуализированный type
из input
будет не number
, а простым text
. A 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; }
По умолчанию в базе данных хранится decimal
со шкалой 2. Чтобы прояснить этот вопрос, я добавляю аннотацию [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
.