ASP.NET MVC:Html.Action / Html.ActionLink和特定于文化的DateTime

时间:2013-12-02 14:47:31

标签: c# asp.net-mvc datetime

我已经在ASP.NET MVC中与文化特定的DateTime争夺了几天,但无济于事。 方案如下:我有一个列表,我想过滤用户提交的DateTime。用户应该以本地化的形式处理日期,在我的案例中,culture和cultureUI设置为“da-DK”,因此日期格式为“dd-mm-yy”。到目前为止,我已设法以所需的格式提交表单提交日期,但Action和ActionLink方法生成的URL用于解释en-US中的日期(“mm / dd / yy”)。

这是一个显示问题的示例项目。 Web.config中的文化被硬编码为“da-DK”:

<globalization culture="da-DK" uiCulture="da-DK" />

首先控制器有两个动作:

using System;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace DateTimeTest.Controllers
{
    public class HomeController : Controller
    {
        public ViewResult Index(DateModel model)
        {
            return View(model);
        }

        public ViewResult Dummy(DateTime? date)
        {
            return View(date);
        }
    }

    public class DateModel
    {
        [DataType(DataType.Date)]
        public DateTime? Date { get; set; }
    }
}

索引是显示表单的操作,用户可以以“dd-mm-yy”格式输入日期。表单被发布到相同的GET方法(正如我所提到的,它假设是过滤功能),它将显示收到的日期。这是Index.cshtml视图:

@model DateTimeTest.Controllers.DateModel

<div>
    @if (Model.Date != null)
    {
        <p>Received @Model.Date</p>
        @Html.ActionLink("Dummy", "Dummy", new {Model.Date})
    }

    @using (Html.BeginForm("Index", "Home", FormMethod.Get))
    {
        @Html.EditorForModel()
    }
</div>

为了使这项工作,我不得不使用自定义模型绑定器,处理DateTime。简化版本如下:

using System;
using System.Web.Mvc;

namespace DateTimeTest.Infrastructure
{
    public class DateTimeBinder: IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            string date = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue;

            DateTime? result = DateTime.Parse(date);

            return result;
        }
    }
}

此活页夹已在Global.asax.cs中注册

ModelBinders.Binders.Add(typeof(DateTime?), new DateTimeBinder());

现在,当我在表格中输入日期“30-12-2013”​​并提交时,索引视图显示消息“已收到30-12-2013 00:00:00”,这在我的意思是正确的。但是,虚拟动作的链接如下所示:

http://localhost:53143/Home/Dummy?Date=12%2F30%2F2013%2000%3A00%3A00

表示Date的查询字符串实际上是“12/30/2013 00:00:00”。单击该链接会在DateTimeBinder的BindModel中显示FormatException,因为日历中没有30个月(它尝试以da-DK格式处理日期,而它获取的日期是en-US中的日期)。我知道如何处理异常本身,但我不知道如何强制系统使用统一的DateTime格式,或者在绑定器中检测它进入的格式并采取相应的行动。我想这可以归结为质疑如何通过Html.Action和Html.ActionLink方法生成URL,尽管我可能错了。

请注意,我理解需要以en-US格式处理GET URL(关于在网络上流传的飞行票据的帖子),但我愿意忽略这一点,因为我正在处理的网站是Intranet网站其中日期仅以da-DK格式使用。任何人都可以帮我解决这个问题吗?提前谢谢。

PS。我正在使用ASP.NET MVC 5.

2 个答案:

答案 0 :(得分:2)

问题似乎是深入挖掘了ActionLink的代码(并通过大量的类进行了大量的方法调用),它有这一行:

builder2.Append(UrlEncode(Convert.ToString(obj3, CultureInfo.InvariantCulture)));

现在代码非常复杂,所以我不能100%确定这是导致你出问题的那条线,但是如果没有其他类似的线路,我会相信它。

所以你问题的原因是你的ActionLink是在一个不变的文化环境中生成而不是你想要的。这不可能解决。

您可以通过使用ToString并指定您的文化(或者可能允许它使用默认值)来修复它。

N.B。上面引用的代码行是通过System.Web.Routing.ParsedRoute.Bind(...)中的Reflector找到的。 ParsedRoute是一个内部类。它在System.Web.dll程序集中。

答案 1 :(得分:0)

我会将文化和养蜂技术硬编码为da-DK

<globalization uiCulture="da-DK" culture="da-DK" />