【问题标题】:Unobtrusive DateTime? Validation in MVC4不显眼的日期时间? MVC4 中的验证
【发布时间】:2012-11-17 09:14:11
【问题描述】:

我将 MVC3 解决方案升级到 MVC4。迁移后,验证器损坏。

如果我选择德语作为语言,我的输入日期是“2013 年 3 月 2 日”。我在 MVC4 中收到验证错误,但在 MVC3 中没有。如果我将格式从“20.03.2013”​​替换为“20/03/2013”​​,它在 MVC4 中有效,但在 MVC3 中无效;-)

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

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

这是我使用的代码。

[必需(ErrorMessageResourceName = "Error_DepartureDate", ErrorMessageResourceType = typeof(Resx.Query))] 公共日期时间?出发日期{得到;放; }

我认为默认模型绑定器有问题,因为呈现的 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=""

当您使用 Visual Studio 2012(安装了 SP1)模板创建新的 Mvc 应用程序时,我将 Jscript 升级到了随附的源代码。这没有影响。

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

公共静态无效 UpdateThreadCulture(CultureInfo 文化) { Thread.CurrentThread.CurrentUICulture = 文化; }

培养模型活页夹是默认活页夹。

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

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

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

更新 2:

我有一个组合框,用户可以在其中选择 16 种不同的语言,每种语言都可能有自己特定的格式。

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

我刚刚得到了关于设置当前文化的提示,这是它应该是正确的证明。当验证器失败时,这段代码不会被命中,看起来它发生在客户端。

公共类 DateTimeModelBinder : IModelBinder { 私有 LogService _log = new LogService(); 公共对象 BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { 对象结果 = null; ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 如果(值结果!= null) { 尝试 { var stateHandler = new StateHandler(controllerContext.HttpContext.Session); 结果 = valueResult.ConvertTo(typeof(DateTime?), stateHandler.Culture); } 抓住 { 尝试 { 结果 = valueResult.ConvertTo(typeof(DateTime?), CultureInfo.InvariantCulture); } 捕捉(例外前) { _log.Error("DateTimeModelBinder 解析异常", ex); _log.KeyValue("AttemptedValue", valueResult.AttemptedValue); } } } 返回结果; } }

为了完整起见,我的文化模型绑定器:

公共类 CultureModelBinder : DefaultModelBinder { 公共覆盖对象 BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { StateHandler stateHandler = new StateHandler(controllerContext.HttpContext.Session); Helper.UpdateThreadCulture(stateHandler.Culture); 返回 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 // 还有更多其他脚本...

添加了通话。输出正确的是“DE”。

var currentLanguage = $("#DepartureDate").attr("data-lang"); 警报(当前语言); $.preferCulture(currentLanguage);

对验证器没有影响...

【问题讨论】:

  • 我自己的问题可能重复:P stackoverflow.com/questions/11756226/…
  • 谢谢,我看到了你的问题。我不使用捆绑包。这是从 MVC3 到 MVC4 的 1:1 升级。我还尝试从模板创建一个新的 MVC4 项目并遇到同样的问题。然后我删除了捆绑,这也没有影响。
  • 您是否覆盖了问题中看到的默认 jquery 日期验证器?
  • 不,一切都是默认的。我可以在新的 MVC4 项目中重现该错误。
  • 如何在 web.config 中为文化和 uiCulture 的 system.web 标签全球化设置文化?

标签: c# asp.net asp.net-mvc asp.net-mvc-3 asp.net-mvc-4


【解决方案1】:

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

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

最后,在模型绑定器中设置文化是非常低效的,因为模型绑定器是一个递归函数,所以在模型重建过程中被调用了数百次,而文化设置操作不是简单的变量设置操作,而是它的成本不可忽略。最好编写一个全局控制器过滤器来处理文化设置(我总是这样做),这样每个请求只执行一次操作

【讨论】:

  • 谢谢,明天试试 ;-)
【解决方案2】:

尝试覆盖默认的日期验证器:

// 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();

【讨论】:

  • 谢谢,目前正在尝试。我希望在不修改太多代码的情况下找到解决方案。如前所述,它可以毫无问题地与 MVC3 一起使用。
  • 我知道并且我真的很想知道到底是什么问题,这个客户端日期选择器验证/格式化让我非常头疼,难以置信。这东西真的没必要。
  • 我可能会考虑将此解决方案与自定义模型绑定器结合使用。我可以将所有文化的日期格式化为 Ansi 日期格式,并使用日期时间重载,我可以分别传递年、月和日。但是让我们拭目以待,看看是否有更好的解决方案:D
【解决方案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 建议将 mvc4 中的新 jquery.validate.js 替换为 MVC3 项目模板中的旧 jquery.validate.js。这可行,但有趣的是,该错误不在 MVC4 中,而在 MVC3 中。

    我们使用 Francesco 描述的方式,请参阅接受的答案。

    【讨论】:

      【解决方案5】:

      如果这仅发生在 Chrome 中,那么这是由于 jquery 版本在日期验证中存在文化错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-17
        • 2014-06-07
        • 2011-12-24
        相关资源
        最近更新 更多