Проверьте дату в определенном формате в ASP.NET MVC 3 - PullRequest
5 голосов
/ 17 июня 2011

У меня есть свойство типа DateTime MyDate в моей ViewModel.Я хочу убедиться, что пользователь вводит только часть даты в текстовое поле в определенном формате (dd.mm.yyyy) и пробовал следующие атрибуты:

[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode=true)]
[RegularExpression(@"^(([0-2]\d|[3][0-1])\.([0]\d|[1][0-2])\.[2][0]\d{2})$",
    ErrorMessage="Failed...")]
public DateTime MyDate { get; set; }

Подпись действия контроллера для HttpPostвыглядит так:

[HttpPost]
public ActionResult Edit(int id, MyViewModel viewModel)
{
    // MyViewModel contains the MyDate property ...
    // ...
    if (ModelState.IsValid)
    {
        // ...
    }
    // ...
}

В представлении Razor я пробовал следующие два способа:

  1. @Html.TextBoxFor(model => model.MyDate)

  2. @Html.EditorFor(model => model.MyDate)

Это не работает, как я хочу.Результат:

  • Проверка на стороне клиента работает, как и ожидалось, с обоими помощниками Html
  • Проверка на стороне сервера всегда завершается неудачей для обоих помощников, даже с действительными датами, такими как "17.06.2011", которые проходятрегулярное выражение.Свойство MyDate правильно заполнено введенной датой в viewModel, которая передается действию.Похоже, что привязка модели работала.
  • Атрибут DisplayFormat учитывается только EditorFor, но не TextBoxFor.TextBoxFor отображает «дд.мм.гггг чч: мм: сс»

Вопросы:

  1. Можно ли вообще применить RegularExpressionAttribute насвойство, которое не string?Если это разрешено, как reg ex оценивается для нестрокового свойства, такого как DateTime на стороне сервера?Это что-то вроде MyDate.ToString() по сравнению с reg ex?(Это объясняет, что валидация завершается неудачно, потому что ToString вернет строку, включающую часть времени, которая не проходит регулярное выражение.)

  2. Является ли атрибут DisplayFormat обычно только для EditorFor и никогда TextBoxFor?

  3. Как правильно проверить дату?

Ответы [ 2 ]

10 голосов
/ 18 июня 2011

Не используйте регулярные выражения для проверки дат, они просто игнорируются.

Различия в культурах могут быть причиной вашей проблемы.Проверка на стороне клиента использует культуру браузера для проверки даты.Так, например, если он настроен на en-US, ожидаемый формат будет MM/dd/yyyy.Если ваш сервер настроен на использование fr-FR, ожидаемый формат будет dd/MM/yyyy.

. Вы можете использовать элемент <globalization> в web.config для установки культуры на стороне сервера.Вы можете настроить его таким образом, чтобы он использовал ту же культуру, что и клиент:

<globalization culture="auto" uiCulture="auto"/>

У Хансельмана есть приятное сообщение в блоге о глобализации и локализации в ASP.NET MVC.

4 голосов
/ 18 июня 2011

Я сейчас выбросил RegularExpression. Кажется, он не подходит для свойства типа DateTime. Затем я создал новый атрибут проверки для DateTime и обнуляемый DateTime:

[AttributeUsage(AttributeTargets.Property, Inherited = false,
    AllowMultiple = false)]
public sealed class DateOnlyAttribute : ValidationAttribute
{
    public DateOnlyAttribute() :
        base("\"{0}\" must be a date without time portion.")
    {
    }

    public override bool IsValid(object value)
    {
        if (value != null)
        {
            if (value.GetType() == typeof(DateTime))
            {
                DateTime dateTime = (DateTime)value;
                return dateTime.TimeOfDay == TimeSpan.Zero;
            }
            else if (value.GetType() == typeof(Nullable<DateTime>))
            {
                DateTime? dateTime = (DateTime?)value;
                return !dateTime.HasValue
                    || dateTime.Value.TimeOfDay == TimeSpan.Zero;
            }
        }
        return true;
    }

    public override string FormatErrorMessage(string name)
    {
        return string.Format(CultureInfo.CurrentCulture,
            ErrorMessageString, name);
    }
}

Использование:

[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode=true)]
[DateOnly]
public DateTime MyDate { get; set; }

Не обеспечивает проверку на стороне клиента. На стороне сервера проверка опирается на привязку модели (чтобы убедиться, что введенная строка вообще может быть преобразована в DateTime). Если пользователь ввел часть времени, отличную от полуночи, включается атрибут DateOnly, и он получает предупреждение о том, что следует вводить только дату.

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