ASP.NET MVC3: 强制控制器使用日期格式dd/mm/yyyy

13

我的日期选择器使用英国格式 dd/mm/yyyy。但是当我提交表单时,ASP.net 明显使用美国格式。 (只接受小于12的天数,即将其认为是月份。)

 public ActionResult TimeTable(DateTime ViewDate)

有没有一种方法可以强制它识别特定的方式?

奇怪的是,其他插入方法似乎会识别正确的格式。

“参数字典包含非空类型 System.DateTime 的参数 ViewDate 的 null 条目,该参数是 Mysite.Controllers.RoomBookingsControllerSystem.Web.Mvc.ActionResult Index(System.DateTime) 方法的非必填参数。可选参数必须是引用类型、可为空类型或声明为可选参数。”


注意:如果你想使用MVC3保存,请同时更改不显眼的JavaScript,否则它甚至不会让你发布。https://dev59.com/c2ct5IYBdhLWcg3wgNcy - IAmGroot
6个回答

17

请阅读这篇文章,它很好地解释了正在发生的事情以及为什么会这样工作。

我知道使用该网站的所有人都在英国,因此可以安全地覆盖默认的DateTime模型绑定程序:

public class DateTimeModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var date = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue;

        if (String.IsNullOrEmpty(date))
            return null;

        bindingContext.ModelState.SetModelValue(bindingContext.ModelName, bindingContext.ValueProvider.GetValue(bindingContext.ModelName));
        try
        {
            return DateTime.Parse(date);
        }
        catch (Exception)
        {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, String.Format("\"{0}\" is invalid.", bindingContext.ModelName));
            return null;
        }
    }
}

阅读所提供的内容后,不同情况变得更加清晰。这篇文章立即调用一个视图,其格式各不相同。而其他文章则存储到数据库中,并因此被正确识别。 - IAmGroot
好的,那么我应该把这段代码放在哪里?如何引用它以便使用。谢谢。 - IAmGroot
3
我在 Binders 目录下有一个独立的文件,其中包含上述代码。然后您需要在 Application_Start() 中注册 binder,类似于 ModelBinders.Binders.Add(typeof(DateTime), new DateTimeModelBinder()) - Adam Flanagan
你的代码不断地翻转日期时间,所以它是英国然后美国然后英国等等等等。好吧 - 它没有解决显示问题。显然仍在使用美国和英国,导致奇怪的效果。我正在使用addday(1),但它仍在翻转。 - IAmGroot
终于可以添加注释了。考虑使用DateTime.TryParseExact(),您可以在其中指定DateTime格式("{0:dd/MM/yyyy}")。 - Gumowy Kaczak
虽然覆盖这个有点奇怪,但它确实有效。只需稍微修改一下以使用区域性格式进行解析。为什么还没有人编辑这个答案呢? - CularBytes

3

您需要使用自定义的ModelBinder来处理DateTime。我之前也遇到了同样的问题。


2
基本上,我的日期选择器使用英国的dd/mm/yyyy格式。
初学者的错误。它应该使用浏览器设置的任何格式。问题不在于格式,而在于客户端和服务器之间的不同格式。服务器应该发出代码,根据协商的语言环境格式化日期,然后服务器也使用此语言环境解析它。
但是当我提交表单时,ASP.NET明显使用美国格式。
不对。这就像说,当我拿到一种香料时,它总是盐,然后你总是拿盐。除非你修改设置,否则您的服务器接受当前协商的语言环境。在执行解析时,请检查线程的当前语言环境设置。

好的,如果datetimepicker使用浏览器设置选项,那么无论datetimepicker的格式如何,它仍将以实际表示的日期时间形式进入asp.net代码中,对吗? - IAmGroot
取决于你的编码方式。也可能是来自一个糟糕编写的日期时间选择器的字符串。你说“我的日期时间选择器”。修复它吧 ;) - TomTom
哎呀 - 可能完全不了解与服务器协商的设置。请查看http://stackoverflow.com/questions/3870605/jquery-datetime-picker-date-format-issue,以了解如何在页面中初始化它 ;) 基本上告诉它使用协商格式。然后它们就匹配了。 - TomTom
我目前已经覆盖了jQuery datetimepicker以使用英国格式。我的电脑是英国格式,但在提交到C#代码时它仍然被读为美国格式。即使有以下覆盖,我仍然不知道如何解决它。 :( - IAmGroot

2

您尝试设置当前文化为en-GB了吗?

protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
     base.Initialize(requestContext);

     CultureInfo cultureInfo = CultureInfo.GetCultureInfo("en-GB");

     Thread.CurrentThread.CurrentCulture = cultureInfo;
     Thread.CurrentThread.CurrentUICulture = cultureInfo;                    
 }

这个应该放在哪里?Global.asax.cs文件中吗? - IAmGroot
1
有几个地方可以放置这段代码,我的例子是覆盖控制器的initialize方法,但你也可以将其放在View.InitializeCulture或Global.asax中。参见此处:http://forums.asp.net/p/1521130/3656712.aspx - Sebastian Piu
除非DateTime来自表单集合,否则此方法无法正常工作。如果它来自查询字符串或路由数据,则文化设置将被忽略。 - Adam Flanagan
我把它放在我的预订控制器的顶部,但它仍然做同样的事情。 :( - IAmGroot
绝对更喜欢在Global.asax.cs中的Application_BeginRequest()方法中添加这个。 - perfectionist

2
你可以做到:
  • globally (in global.asax under Application_Start() ):

    ModelBinders.Binders.Add(typeof(DateTime), new DateTimeModelBinder()); 
    
  • for a method:

        public ActionResult TimeTable([Binder(typeof(DateTimeModelBinder)]DateTime ViewDate)
    
  • for a custom model class - ah no, no posibility cause you use struct DateTime ;-)

啊,抱歉我无法对亚当的帖子进行评论 - 它是基于他的代码的。

0

根据《Pro MVC3》一书的示例,从我的BindigTools中绑定DateTime?(可空)。

    public static DateTime? GetValueNDateTime(ModelBindingContext context, string searchPrefix, string key, string format)
    {
        ValueProviderResult vpr = context.ValueProvider.GetValue(searchPrefix + key);
        DateTime outVal;
        if (DateTime.TryParseExact(vpr.AttemptedValue, format, null, System.Globalization.DateTimeStyles.None, out outVal))
        {
            return outVal;
        }
        else
        {
            return null;
        }
    }

它使用精确解析,因此您不应该对解析的日期有任何问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接