Подтвердить что ты не робот

Ненавязчивая дата-время? Проверка в MVC4

Я обновил MVC3-решение до MVC4. После миграции валидатор не работает.

Моя дата ввода, если я выбираю немецкий как язык, составляет "20.03.2013". Я получаю ошибку проверки в MVC4, но не в MVC3. Если я заменю формат от "20.03.2013" до "20/03/2013", он работает в MVC4, но не в MVC3; -)

Я устанавливаю культуру пользовательского интерфейса текущего потока в немецкий. Результат значений ResX находится на правильном языке, , поэтому я знаю, что в культуре не должно быть ошибок., только для самого сайта. Сообщения об ошибках написаны на английском языке, но сайт находится на немецком языке.

Я предполагаю, что это означает, что валидатор использует неправильную культуру пользовательского интерфейса.

Вот код, который я использую.

[Required(ErrorMessageResourceName = "Error_DepartureDate", ErrorMessageResourceType = typeof(Resx.Query))]
public DateTime? DepartureDate { get; set; }

Я предполагаю, что что-то не так с привязкой к модели по умолчанию, поскольку рендеринг html выглядит хорошо:

data-lang="de" data-mindate="3" data-val="true" data-val-required="Bitte geben Sie das gewünschte Reisedatum des Hinflugs ein." id="DepartureDate" name="DepartureDate" tabindex="3" type="text" value="" 

Я обновил Jscript до источников, которые отправляются при создании нового приложения Mvc с использованием шаблонов Visual Studio 2012 (SP1). Это не повлияло.

У меня есть CultureModelBinder, который читает текущую культуру из сеанса и устанавливает культуру с помощью небольшой вспомогательной функции.

public static void UpdateThreadCulture(CultureInfo culture)
{
  Thread.CurrentThread.CurrentUICulture = culture;            
}        

Связывание модели культуры является связующим по умолчанию.

ModelBinders.Binders.DefaultBinder = new CultureModelBinder();
ModelBinders.Binders.Add(typeof(DateTime?), new DateTimeModelBinder());
// and many, many more

Возможно, что-то изменилось в порядке выполнения с mvc4, что привело к проблеме?

Обновление: проект использует .NET Framework 4.5 в качестве целевой.

Обновление 2:

У меня есть поле со списком, в котором пользователь может выбрать 16 разных языков, каждый из которых может иметь собственное форматирование.

например. DE-de → DD.MM.YYYY; en-en → DD/MM/YYYY; en-us → MM/DD/YYYY

У меня только намек на настройку текущей культуры, вот доказательство того, что это должно быть правильно, как есть. Этот код не попадает, когда валидаторы терпят неудачу, похоже, что это происходит на стороне клиента.

   public class DateTimeModelBinder : IModelBinder
    {
        private LogService _log = new LogService();

        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {            
            object result = null;
            ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            if (valueResult != null)
            {
                try
                {
                    var stateHandler = new StateHandler(controllerContext.HttpContext.Session);                    
                    result = valueResult.ConvertTo(typeof(DateTime?), stateHandler.Culture);                                       
                }
                catch
                {
                    try
                    {
                        result = valueResult.ConvertTo(typeof(DateTime?), CultureInfo.InvariantCulture);
                    }
                    catch (Exception ex)
                    {
                        _log.Error("DateTimeModelBinder parse exception", ex);
                        _log.KeyValue("AttemptedValue", valueResult.AttemptedValue);                                           
                    }                    
                }
            }
            return result;
        }
    }

и для полноты моего связующего для модели культуры:

  public class CultureModelBinder : DefaultModelBinder
    {      
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            StateHandler stateHandler = new StateHandler(controllerContext.HttpContext.Session);
            Helper.UpdateThreadCulture(stateHandler.Culture);

            return base.BindModel(controllerContext, bindingContext);
        }        
    }

Обновление: возможно, существует корреляция с этой проблемой: http://connect.microsoft.com/VisualStudio/feedback/details/705643/a-data-val-date-attribute-is-generated-for-time-fields-in-asp-net-mvc-4

Обновление: Прочтите следующую статью: http://weblogs.asp.net/scottgu/archive/2010/06/10/jquery-globalization-plugin-from-microsoft.aspx

попробовал следующее:

Загрузите скрипты в следующем порядке:

/Scripts/jquery-1.8.3.min.js
/Scripts/globalize.js
/Scripts/cultures/globalize.cultures.js
// and much more other scripts...

добавлен вызов. выход был правильно "DE".

        var currentLanguage = $("#DepartureDate").attr("data-lang");
        alert(currentLanguage);       
        $.preferCulture(currentLanguage);

Не влияет на валидаторы...

4b9b3361

Ответ 1

Дело в том, что Mvc3 не проверяет на всех датах на стороне клиента, которая является точкой. Вы просто настроили культуру на стороне сервера... но настройки вашей культуры совсем не отражаются на стороне клиента... по крайней мере, движок Mvc не делает это автоматически. Единственный способ правильно обрабатывать даты и числа на стороне клиента с культурами, которые отличаются от английского, - это использовать библиотеку глобализации aa javascript, которая может правильно определять даты во всех культурах и устанавливать культуру на стороне клиента равной культуре на стороне сервера, то вам необходимо правильно определить все методы проверки для использования глобализованных функций. Прочитайте это сообщение в своем блоге, в котором разъясняется, как правильно обрабатывать глобализацию на стороне клиента: http://www.dotnet-programming.com/post/2011/12/14/Globalization-Validation-and-DateNumber-Formats-in-AspNet-MVC.aspx

Кроме того, пожалуйста, не путайте CurrentCulture с CurrentUICulture. CurrentUICulture не влияет на все способы обработки чисел или дат, но только файлы ресурсов, содержащие специфические ресурсы для культуры, такие как локализованные строки.

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

Ответ 2

Попробуйте перезаписать валидатор даты по умолчанию:

// Replace dots so jq validator can understand what going on
$(function () {
    $.validator.addMethod(
    "date",
    function (value, element) {
        var s = value;
        s = value.replace(/\./g, '/');

        // Chrome requires tolocaledatestring conversion, otherwise just use the slashed format
        var d = new Date();
        return this.optional(element) || !/Invalid|NaN/.test(new Date(d.toLocaleDateString(value))) || !/Invalid|NaN/.test(new Date(s));
    },
    ""
    );
});

$.validator.unobtrusive.parse();

Ответ 3

Просматривая код с помощью ILSpy, это, как представляется, новый внедренный ClientDataTypeModelValidatorProvider, который добавляет атрибут data-val-date.

Если вы хотите вернуться к функциям стиля MVC3, просто удалить этот провайдер из списка поставщиков проверки модели, делает трюк.

Это не решает проблему, но в нескольких строках кода могут быть устранены проблемы, вызванные отсутствием валидации jquery глобализации.

using System.Web.Mvc;

...

protected void Application_Start()
{
  var providers = ModelValidatorProviders.Providers;
  var clientDataTypeModelValidatorProvider = providers.OfType<ClientDataTypeModelValidatorProvider>().FirstOrDefault();
  if ( clientDataTypeModelValidatorProvider != null )
  {
    providers.Remove( clientDataTypeModelValidatorProvider );
  }

  ...
}

Ответ 4

Microsoft предлагает заменить новый jquery.validate.js из mvc4 на старый jquery.validate.js из шаблона проекта MVC3. Это работает, но самое смешное, ошибка не в MVC4, это было в MVC3.

Мы используем способ, описанный Франческо, см. принятый ответ.

Ответ 5

Если это происходит только в Chrome, это связано с тем, что версия jquery имеет ошибку культуры при проверке дат.