Необходимость демонстрации использования DataTypeAttribute (как описано в руководстве Microsoft) - PullRequest
1 голос
/ 14 мая 2019

Я перехожу из ASP.NET MVC в ASP.NET Core и во время изучения документации от Microsoft на этой странице https://docs.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/validation?view=aspnetcore-2.2

Я прочитал эту строку о DataTypeAttribute:

Атрибут DataType может позволить платформе ASP.NET Core выбрать правильный шаблон поля для визуализации данных.DisplayFormat, если он используется сам по себе, использует шаблон строки.

Это звучит мне неясно, все, что я знаю о DataTypeAttribute, - это то, что упомянуто в приведенной выше строке (на той же странице):

Браузер может включать функции HTML5 (например, для отображения элемента управления календаря, символа валюты, соответствующего локали, ссылок электронной почты и т. Д.)

Так что это означает первую цитатудействительно говорит о чем-то отличном от второго, не могли бы вы дать мне более четкое объяснение того, что это значит (в первой цитате), а также (если возможно) некоторый интересный фрагмент кода, чтобы продемонстрировать это?Спасибо.

ОБНОВЛЕНИЕ

Точнее о том, что я хочу здесь, на самом деле разница между двумя кавычками, как показано в следующем снимке:

enter image description here

Я понимаю первую цитату (на снимке), но на самом деле вторая приводит меня в замешательство, поэтому я прошу более четкое объяснение.2 пункта в одном таком списке не могут быть одинаковыми, не так ли?

1 Ответ

1 голос
/ 14 мая 2019

Атрибут 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}" },
    };

В результате отображается представление:

enter image description here

Вот как 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...