Ненавязчивая проверка даты MVC3 в отформатированной дате - PullRequest
7 голосов
/ 09 ноября 2011

У меня есть поле даты (я использую средство выбора даты jquery ui) в форме, которую я отформатировал, например так:

ViewModel

[DisplayFormat(DataFormatString = "{0:dd-MMM-yyyy}", ApplyFormatInEditMode = true)]
public DateTime FooDate { get; set; }

View

@Html.EditorFor(m => m.FooDate)

Это правильно показывает дату так, как я хочу, например, 09-Nov-2011

Проблема, с которой я сталкиваюсь, возникает, когда я нажимаю "Отправить". Мне все время говорят, что дата недействительна .... она действительна, глупая вещь!

Есть ли способ, я могу заставить jquery / ненавязчивый javascript игнорировать это поле или позволить этому формату пройти? Пока что единственный способ заставить форму работать - если я не отформатирую дату или не использую {0: d} в качестве формата даты для нее.

Редактировать : Я создал совершенно отдельный макет + представление + контроллер + модель для тестирования этой глупости. Все еще не работает в IE / Safari. У меня есть последние jquery.validate / ненавязчивые файлы из Nuget.

Мой layout пуст. Он просто загружает следующие файлы:

"jquery-1.7.min.js"
"jquery-ui-1.8.16.min.js"
"jquery.validate.min.js"
"jquery.validate.unobtrusive.min.js"

Моя TestViewModel проста:

public class TestViewModel
{
    [Display(Name = "Test Date:")]
    [DisplayFormat(DataFormatString = "{0:dd/MMM/yyyy}", ApplyFormatInEditMode = true)]
    public DateTime? TestDate { get; set; }
}

Мой TestController работает следующим образом:

public class TestController : Controller
{
    public ActionResult Index()
    {
        var m = new TestViewModel();
        m.TestDate = DateTime.Now;
        return View(m);
    }
}

My View:

@using (Html.BeginForm())
{
    ViewContext.FormContext.ValidationSummaryId = "valSumId";
    @Html.ValidationSummary(false, "The following errors were found:");
    @Html.AntiForgeryToken()

    @Html.LabelFor(m => m.TestDate)
    <input type="date" id="TestDate" value="@Model.TestDate.Value.ToString("dd/MMM/yyyy")" />
    <input type="submit" />
}

Не работает.

Вы знаете, что раздражает? Если я изменю TestDate на строку, она все равно не будет выполнена.

Ответы [ 10 ]

4 голосов
/ 21 ноября 2012

Я думаю, что есть проблема с дефисом ("-") в строке формата:

[DisplayFormat(DataFormatString = "{0:dd-MMM-yyyy}", ApplyFormatInEditMode = true)]

Кажется, что ненавязчивая проверка не принимает дефис для форматирования даты по умолчанию.* В моем случае мне пришлось добавить пользовательский метод на стороне клиента:

$.validator.methods.date = function (value, element) {
    var s = value;
    s = value.replace(/\-/g, '/');

    return this.optional(element) || !/Invalid|NaN/.test(new Date(s));
};

, как реализовано здесь

3 голосов
/ 11 ноября 2011

Похоже, что jquery.validate.unobtrusive имеет проблему с input type="date". Это должна быть ошибка, которая возникает только в IE и Safari.

Когда я удалил ненавязчивый файл JS, он отправил форму штрафа. Когда я снова добавил ненавязчивый файл js и изменил тип ввода на текст, это сработало.

Досадная ошибка. Необходимо исправить.

2 голосов
/ 09 ноября 2011

Здесь действительно две вещи:

  1. Проверка на стороне клиента
  2. Проверка на стороне сервера

Оба должны использовать один и тот же формат, чтобы это работало,Давайте сначала разберемся с проверкой на стороне сервера.Для полей DateTime можно написать настраиваемый механизм связывания модели, который будет использовать формат, указанный для отображения при их привязке.Вот пример такой связующей модели .

Далее мы должны иметь дело с проверкой на стороне клиента.Для этого вы можете написать пользовательское правило, которое будет прикреплено к заданным элементам:

<script type="text/javascript">
    $.validator.addMethod(
        'myDateFormat', function (value, element) {
            // TODO: put your validation logic here that will parse the string
            // and validate it
            return false;
        },
        'Please enter a date in the format dd-MMM-yyyy'
    );

    $(function () {
        // we attach the custom validation rule to the given input element
        $('#FooDate').rules('add', 'myDateFormat');
    });
</script>

Вы также можете использовать адаптеры с пользовательским атрибутом .

1 голос
/ 09 июня 2017

Как писал Лукиер, могут возникнуть проблемы, связанные с файлами jquery.validate * .min.js , особенно если вы добавили в эти файлы свою собственную проверку. Простой ответ, который я нашел, который работал для меня, когда система окончательного выпуска не проверила даты в IE (Chrome работал без проблем), состоял в том, чтобы просто удалить предварительно упакованные минимизированные файлы проверки и позволить зверю справиться со своим собственным минимизацией от «мастера». "файлы. Жаль только, что я не связывал ответ Лукера с решением ранее ...

(Вероятно, я бы опубликовал это как комментарий, но, видимо, я еще не набрал достаточно репутации: надо стараться!)

1 голос
/ 08 марта 2017

На самом деле это не ошибка в браузере, проблемы проверки клиента могут возникнуть из-за ошибки MVC (даже в MVC 5) в jquery.validate.unobtrusive.min.js , которая не принимает дату/ формат даты / времени любым способом .К сожалению, вы должны решить это вручную.

Мое окончательно работающее решение:

Вы должны включить ранее:

@Scripts.Render("~/Scripts/jquery-3.1.1.js")
@Scripts.Render("~/Scripts/jquery.validate.min.js")
@Scripts.Render("~/Scripts/jquery.validate.unobtrusive.min.js")
@Scripts.Render("~/Scripts/moment.js")

Вы можете установить moment.js, используя:

Install-Package Moment.js

И наконец вы можете добавить исправление для анализатора формата даты:

$(function () {
    $.validator.methods.date = function (value, element) {
        return this.optional(element) || moment(value, "DD.MM.YYYY", true).isValid();
    }
});
1 голос
/ 11 ноября 2011

В моем случае я использую текстовое поле для даты, чтобы оно не вызывало проблем при проверке jquery:

 <div class="editor-field">
    @Html.TextBox("ExpiryDate", String.Format("{0:ddd, dd MMM yyyy}", DateTime.Now), new { id = "expirydate" })
    @Html.ValidationMessageFor(model => model.ExpiryDate)
</div>

Так почему бы вам не попробовать отформатировать дату как эта, а не использовать тип ввода= дата?

Надеюсь, эта помощь:)

0 голосов
/ 16 января 2014

Довольно старая эта тема. Просто приземлился здесь с похожими проблемами. В другой ветке я читал, что могут быть проблемы с несовместимостью версий всеми этими библиотеками * .js, которые каким-то образом участвуют в проверке. Возможно, следующая ссылка может помочь другим читателям найти здесь: https://stackoverflow.com/a/16551039

Надеюсь, это поможет

0 голосов
/ 30 июля 2012

Просто хотел бы сделать небольшой комментарий к этой строке, если у кого-то еще возникнут проблемы с этим позже:

<input type="date" id="TestDate" value="@Model.TestDate.Value.ToString("dd/MMM/yyyy")" />

В некоторых случаях (по крайней мере, в моем случае ранее) это будет переводиться в этот формат: "01.01.2012 ", потому что в некоторых культурах вы не можете указать такие слеши, чтобы фактически отформатировать их так, они просто превратят их в точки, поэтому мне пришлось написать:

@Model.TestDate.Value.ToString("dd\/MMM\/yyyy");

Что и дало мне"01/01/2012".

0 голосов
/ 24 марта 2012

У меня была такая же проблема, это сводило меня с ума!По сути, валидация mvc всегда будет отображать объекты DateTime для запроса значения в текстовом поле.Зачем?Потому что он напрямую связан с DateTime объектом.Если вы объявите свой ViewModel с?символ, вы сделаете его обнуляемым.Таким образом, вам не понадобится проверка:

public class MyViewModel
{
    DateTime? StartDate { get; set; }
}

Надеюсь, это поможет

0 голосов
/ 11 ноября 2011

Вы пытались просто изменить тип на:

@Html.TextBoxFor(model => model.startDate, new { @class = "date" })

У меня возникла та же проблема с EditorFor ..., поэтому я изменил ее на это, а затем применил свой указатель даты jquery к классу 'date', добавленному в текстовое поле.

...