Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
Поскольку в разных регионах применяются разные форматы дат, то использование дат в приложение имеет определенные особенности. Например, пусть имеется следующая модель:
public class User { public int Id { get; set; } [Display(Name = "Имя")] public string Name { get; set; } [DataType(DataType.Date)] [DisplayFormat(DataFormatString = "{0:dd'/'MM'/'yyyy}", ApplyFormatInEditMode = true)] [Display(Name = "Дата рождения")] public DateTime Date { get; set; } }
В данном случае мы ориентированы на формат dd/MM/yyyy, как показывает атрибут DisplayFormat
.
В представлении используются скрипты валидации и виджет jQuery DatePicker для выбора дат:
@model DateLocalizationApp.Models.User @{ ViewBag.Title = "Create"; } <h2>Добавление модели</h2> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>Пользователь</h4> <hr /> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) <div class="form-group"> @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Date, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Date, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Date, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Create" class="btn btn-default" /> </div> </div> </div> } @section Scripts { @Scripts.Render("~/bundles/jqueryval") <link href='@Url.Content("~/Content/themes/base/all.css")' rel="stylesheet" type="text/css" /> <script src='@Url.Content("~/Scripts/jquery-ui-1.11.4.min.js")' type="text/javascript"></script> <script type="text/javascript"> $(function () { $("input[type='date']") .datepicker({ dateFormat: 'dd/mm/yy' }) .get(0).setAttribute("type", "text"); $.datepicker.regional['ru'] = { prevText: 'Пред', nextText: 'След', monthNames: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'], monthNamesShort: ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'], dayNames: ['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'], dayNamesShort: ['вск', 'пнд', 'втр', 'срд', 'чтв', 'птн', 'сбт'], dayNamesMin: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'], weekHeader: 'Не', dateFormat: 'dd/mm/yy', firstDay: 1, isRTL: false, showMonthAfterYear: false, yearSuffix: '' }; $.datepicker.setDefaults($.datepicker.regional['ru']); }); </script> }
В контроллере перед сохранением модель проходит валидацию:
[HttpPost] public ActionResult Create(User user) { if(ModelState.IsValid) { db.Users.Add(user); db.SaveChanges(); } return View(user); }
И при стандартном ходе событий несмотря на то, что мы введем обычную вроде дату, мы получим ошибку:
Потому что стандартная библиотека валидации javascript, которую предоставляет Microsoft, ориентируется на формат mm/dd/yy, у нас же datepicker использует формат dd/mm/yy.
Чтобы решить проблему, надо переопределить функцию валидатора. Для этого после определения настроек datepicker переопределим функцию валидатора для выбора даты:
@section Scripts { @Scripts.Render("~/bundles/jqueryval") <link href='@Url.Content("~/Content/themes/base/all.css")' rel="stylesheet" type="text/css" /> <script src='@Url.Content("~/Scripts/jquery-ui-1.11.4.min.js")' type="text/javascript"></script> <script type="text/javascript"> $(function () { $("input[type='date']") .datepicker({ dateFormat: 'dd/mm/yy' }) .get(0).setAttribute("type", "text"); $.datepicker.regional['ru'] = { prevText: 'Пред', nextText: 'След', monthNames: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'], monthNamesShort: ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'], dayNames: ['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'], dayNamesShort: ['вск', 'пнд', 'втр', 'срд', 'чтв', 'птн', 'сбт'], dayNamesMin: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'], weekHeader: 'Не', dateFormat: 'dd/mm/yy', firstDay: 1, isRTL: false, showMonthAfterYear: false, yearSuffix: '' }; $.datepicker.setDefaults($.datepicker.regional['ru']); $.validator.addMethod('date', function (value, element) { var ok = true; try { $.datepicker.parseDate('dd/mm/yy', value); } catch (err) { ok = false; } return ok; }); }); </script> }
Теперь для проверки используется функция $.datepicker.parseDate
. Если виджет сможет распарсить дату, то возвращается true. Если же
в процессе парсинга возникнет ошибка, то возвращается false.
После исправления при запуске проекта в Visual Studio все заработает. Но при размещении на зарубежном хостинге, например, на том же somee.com мы можем столкнуться с другой проблемой:
Несмотря на то, что на локальной машине все работало, на хостинге не работает. Потому что текущая культура может отличаться, и в соответствии с текущей культурой может использоваться другой формат даты. В данном случае ошибка будет возникать при валидации на сервере.
Рещением в данной ситуации будет явное указание культуры с помощью элемента globalization в файле web.config в узле system.web:
<system.web> <globalization culture="ru-RU" uiCulture="ru" /> <!-- остальное содержимое system.web-->
Теперь на стороне сервера также будет использоваться дата в формате dd/MM/yyyy.