日期与特定文化的模型无关

Date not binding with model for specific culture

当文化选择 en-US 时,我试图在两种文化(en-US 和 fr-FR)的模型中绑定日期。 用户选择用于创建条目的项目语言。例如 : 在 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"})

日期选择器和解析脚本:

$(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 和 returns 显示错误留言:

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

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

请帮忙。 谢谢

asp.netmvc 中的默认模型绑定器知道日期本地化问题。要使其以指定的文化解析日期,您需要在调用操作方法之前设置 CurrentCulture。我知道执行此操作的可能方法很少。

全球化元素

Globalization element 可以自动将 CurrentCulture 设置为用户的 OS 默认值。 Web.config:

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

因此,如果用户来自 en-US 本地化 OS,日期将以 en-US 格式解析,来自 fr-FR 本地化 OS - 以 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);
    }
}

根据 action/controller 使用它作为属性或将其添加到 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());

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

   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);
            }

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