日期不与特定文化的模型绑定

时间:2015-06-12 10:47:16

标签: jquery asp.net-mvc datetime momentjs globalization

当我们选择文化时,我正试图在两种文化(en-US和fr-FR)的模型中绑定日期。 用户选择用于创建条目的Item语言。例如 : 在en-US中添加新闻|在fr-FR中添加新闻

型号:

[Column(TypeName = "datetime2")]
public DateTime CreatedOn { get; set; }

查看:

@Html.TextBox("CreatedOn", Model.CreatedOn, new { @class = "form-control", @id = "datepicker" , @type="text"})

datepicker和解析的脚本:

$(document).ready(function () {
        $('#datetimepicker2').datetimepicker({
            locale: '@Model.CultureInfoCode',
            format: 'L'
        }).data("DateTimePicker").date();
        //$('#datetimepicker2').moment().format("MM/dd/YYYY");
    });

$(document).ready(function () {
    $.validator.methods.date = function (value, element) {
        moment.locale('@Model.CultureInfoCode'); // CultureInfoCode is the culture of item being entered. 
        return moment(value);
        //parseDate(value, null, "@Model.CultureInfoCode");
           // return this.optional(element) || Globalize.parseDate(value) !== null;
        }
});

解析日期似乎也可以正常工作。模型绑定所有值,包括日期,如果为整个网站选择的文化(en-US )匹配输入项目的文化(即添加英文新闻(en-US))。但是当我用法语添加新闻(fr-FR)并输入日期为26/01/0001时,它会绑定除日期之外的所有字段,并在模型中给出值为1/1/0001并返回显示错误消息的相同视图:

**The value '26/01/0001' is not valid for 'CreatedOn' .**

model.Validate在控制器中也是假的。

请帮忙。 感谢

3 个答案:

答案 0 :(得分:1)

asp.net mvc中的默认模型绑定器知道日期本地化问题。要使其在指定区域性中解析日期,您需要在调用操作方法之前设置CurrentCulture。我知道几种可行的方法。

全球化元素

Globalization element可以自动将CurrentCulture设置为用户的操作系统默认值。 web.config中:

<globalization culture="auto" uiCulture="auto" />

因此,如果用户来自en-US本地化操作系统,则日期将以en-US格式解析,来自fr-FR本地化操作系统 - 采用fr-FR格式,依此类推。

动作过滤器

如果需要手动设置CurrentCulture,可以使用操作过滤器来执行此操作。更多信息可以在this answer中找到。如果在url中指定了区域性代码,则可以使用此方法。

定义路线:

routes.MapRoute(
    "DefaultLocalized",
    "{culture}/{controller}/{action}/{id}",
    new { culture = "en-US", controller = "Home", action = "Index", id = UrlParameter.Optional }
);

定义动作过滤器:

public class InternationalizationAttribute : ActionFilterAttribute 
{
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    {
        string culture = (string)filterContext.RouteData.Values["culture"] ?? "en-US";

        Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(culture);
        Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture);
    }
}

将每个操作/控制器用作属性,或将其添加到Application_Start()中的全局过滤器集合中:

GlobalFilters.Filters.Add(new InternationalizationAttribute());

模型粘合剂

另一种方法是重新实现DateTime类型的模型绑定器。更多信息here。例如,您在表单中有文化字段。最简单的模型粘合剂:

public class DateTimeBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var provider = bindingContext.ValueProvider;
        var cultureValue = provider.GetValue("culture");
        var dateValue = provider.GetValue(bindingContext.ModelName);

        var cultureInfo = CultureInfo.CurrentCulture;
        if (cultureValue != null)
            cultureInfo = CultureInfo.GetCultureInfo(cultureValue.AttemptedValue);

        return dateValue.ConvertTo(typeof(DateTime), cultureInfo));
    }
}

在Application_Start()中添加绑定到集合:

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

答案 1 :(得分:1)

谢谢ranquild,它解决了这个问题。虽然我从Request对象中选择了文化,如下所示。因为我需要用户输入的项目文化而不是全球化设置。

   public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
            {
                string cultureName = controllerContext.HttpContext.Request.Form["CultureInfoCode"];
                var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
                System.Globalization.CultureInfo cultureinfo = new System.Globalization.CultureInfo(cultureName);
                return value.ConvertTo(typeof(DateTime), cultureinfo);
            }

答案 2 :(得分:0)

在我们的例子中,我们在JQuery中的视图上设置了一个默认日期,由于某种原因导致绑定失败。我们删除了设置日期的JQuery,并从控制器中设置了viewmodel中的默认日期,以解决问题。