不引人注意的DateTime? 在MVC4中validation

我将MVC3解决方案升级为MVC4。 迁移后,validation程序已损坏。

如果我选择德语作为语言,我的输入日期是“20.03.2013”​​。 我在MVC4中得到validation错误,但在MVC3中没有。 如果我将格式从“20.03.2013”​​替换为“20/03/2013”​​,它适用于MVC4,但不适用于MVC3 😉

我将当前线程的UI文化设置为德语。 ResX值的输出是正确的语言, 所以我知道文化不应该有错误。 ,仅适用于网站本身。 错误消息是英文的,但该网站是德语。

我认为这意味着validation器使用了错误的UI文化。

这是我使用的代码。

 [必需(ErrorMessageResourceName =“Error_DepartureDate”,ErrorMessageResourceType = typeof(Resx.Query))]
公共日期时间?  DepartureDate {get; 组;  }

我假设默认模型绑定器有问题,因为渲染的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升级到使用Visual Studio 2012(已安装SP1)模板创建新Mvc应用程序时发布的源代码。 这没有任何影响。

我有一个CultureModelBinder,它从Session中读取当前的文化,并使用一个小帮助函数设置文化。

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

culture文件模型binder是默认的binder。

 ModelBinders.Binders.DefaultBinder = new CultureModelBinder();
 ModelBinders.Binders.Add(typeof(DateTime?),new DateTimeModelBinder());
 //还有很多很多

也许mvc4的执行顺序发生了变化,导致问题?

更新:该项目使用.NET Framework 4.5作为目标。

更新2:

我有一个combobox,用户可以选择16种不同的语言,每种语言都有自己特定的格式。

例如DE-de – > DD.MM.YYYY; en-en – > DD / MM / YYYY; en-us – > MM / DD / YYYY

我刚刚提到了关于设置当前文化的暗示,这里certificate它应该是正确的。 当validation器失败时,不会触发此代码,看起来它发生在客户端。

    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)
             {
                尝试
                 {
                     var stateHandler = new StateHandler(controllerContext.HttpContext.Session);                    
                     result = valueResult.ConvertTo(typeof(DateTime?),stateHandler.Culture);                                       
                 }
                抓住
                 {
                    尝试
                     {
                         result = valueResult.ConvertTo(typeof(DateTime?),CultureInfo.InvariantCulture);
                     }
                     catch(Exception ex)
                     {
                         _log.Error(“DateTimeModelBinder parse exception”,ex);
                         _log.KeyValue(“AttemptedValue”,valueResult.AttemptedValue);                                           
                     }                    
                 }
             }
            返回结果;
         }
     }

为了完整我的文化模型粘合剂:

   public class CultureModelBinder:DefaultModelBinder
     {      
        公共覆盖对象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净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
 //以及更多其他脚本......

加了电话。 输出正确“DE”。

         var currentLanguage = $(“#DepartureDate”)。attr(“data-lang”);
        警报(currentLanguage);       
         $ .preferCulture(currentLanguage);

对validation者没有影响……

关键是Mvc3不会在客户端的所有日期validation这一点。 你只需在服务器端设置文件….但你的文化设置根本没有反映在客户端…至少Mvc引擎不会自动执行。 使用与英语不同的文化在客户端正确处理日期和数字的唯一方法是使用能够在所有文化中正确解析日期的javascript全球化库,并将客户端文化设置为与服务器端文化相同,那么你必须正确地重新定义所有validation方法以使用全球化函数。 请阅读我的博客文章,阐明如何在客户端处理正确的全球化: http : //www.dotnet-programming.com/post/2011/12/14/Globalization-Validation-and-DateNumber-Formats-in -AspNet-MVC.aspx

此外,请不要将CurrentCulture与CurrentUICulture混淆CurrentUICulture不会影响所有数字或日期的处理方式,而只会影响包含文化特定资源(如本地化字符串)的资源文件。

最后,在模型绑定器中设置文化是非常不合理的,因为模型绑定器是递归函数,因此在模型重建期间它被调用了数百次,并且文化设置操作不是简单的变量设置操作,而是具有不可忽视的成本。 最好编写一个全局控制器filter来处理文化设置(我总是这样做),因此每个请求只执行一次操作

尝试覆盖默认日期validation器:

// Replace dots so jq validator can understand what's 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(); 

使用ILSpy查看代码,它似乎是新引入的ClientDataTypeModelValidatorProvider,它正在添加data-val-date属性。

如果要恢复到MVC3样式function,那么只需从模型validation提供程序列表中删除该提供程序即可。

它没有解决问题,但在几行代码中可能会消除由jqueryvalidation缺乏全球化引起的问题。

 using System.Web.Mvc; ... protected void Application_Start() { var providers = ModelValidatorProviders.Providers; var clientDataTypeModelValidatorProvider = providers.OfType().FirstOrDefault(); if ( clientDataTypeModelValidatorProvider != null ) { providers.Remove( clientDataTypeModelValidatorProvider ); } ... } 

Microsoft建议使用MVC3项目模板中的旧jquery.validate.js从mvc4替换新的jquery.validate.js。 这很有用,但有趣的是,bug不在MVC4中,而是在MVC3中。

我们使用Francesco描述的方式,看到接受的答案。

如果这只发生在Chrome中,则是由于jquery版本在日期validation中存在文化错误。