57

如何在 asp.net mvc 4 中强制日期时间的格式?在显示模式下,它按我的意愿显示,但在编辑模式下却没有。我正在使用 displayfor 和 editorfor 和 applyformatineditmode=true 和 dataformatstring="{0:dd/MM/yyyy}" 我试过的:

  • web.config(两者)中的全球化与我的文化和 uiculture。
  • 在 application_start() 中修改文化和 uiculture
  • 日期时间的自定义模型绑定器

我不知道如何强制它,我需要输入日期为 dd/MM/yyyy 而不是默认值。

更多信息:我的视图模型是这样的

    [DisplayName("date of birth")]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
    public DateTime? Birth { get; set; }

鉴于我使用@Html.DisplayFor(m=>m.Birth)但它按预期工作(我看到格式)并输入我使用的日期,@Html.EditorFor(m=>m.Birth)但如果我尝试输入类似 13/12/2000 的内容会失败,错误是它不是有效日期(12/ 13/2000 和 2000/12/13 按预期工作,但我需要 dd/MM/yyyy)。

自定义模型绑定器在 application_start() b/c 中调用,我不知道还有哪里。

使用<globalization/>我尝试过的culture="ro-RO", uiCulture="ro"其他文化,这些文化会给我 dd/MM/yyyy。我还尝试在 application_start() 中基于每个线程设置它(这里有很多例子,关于如何做到这一点)


对于所有将阅读此问题的人:只要我没有客户验证,Darin Dimitrov 的答案似乎就可以工作。另一种方法是使用自定义验证,包括客户端验证。我很高兴在重新创建整个应用程序之前发现了这一点。

4

3 回答 3

103

啊啊啊,现在清楚了。您似乎在绑定值时遇到问题。不是在视图上显示它。事实上,这是默认模型绑定器的错误。您可以编写并使用一个自定义的,它将考虑[DisplayFormat]您模型上的属性。我在这里说明了这样一个自定义模型绑定器:https ://stackoverflow.com/a/7836093/29407


显然有些问题仍然存在。这是我在 ASP.NET MVC 3 和 4 RC 上的完整设置。

模型:

public class MyViewModel
{
    [DisplayName("date of birth")]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
    public DateTime? Birth { get; set; }
}

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel
        {
            Birth = DateTime.Now
        });
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

看法:

@model MyViewModel

@using (Html.BeginForm())
{
    @Html.LabelFor(x => x.Birth)
    @Html.EditorFor(x => x.Birth)
    @Html.ValidationMessageFor(x => x.Birth)
    <button type="submit">OK</button>
}

自定义模型绑定器的注册Application_Start

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

以及自定义模型绑定器本身:

public class MyDateTimeModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var displayFormat = bindingContext.ModelMetadata.DisplayFormatString;
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        if (!string.IsNullOrEmpty(displayFormat) && value != null)
        {
            DateTime date;
            displayFormat = displayFormat.Replace("{0:", string.Empty).Replace("}", string.Empty);
            // use the format specified in the DisplayFormat attribute to parse the date
            if (DateTime.TryParseExact(value.AttemptedValue, displayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
            {
                return date;
            }
            else
            {
                bindingContext.ModelState.AddModelError(
                    bindingContext.ModelName,
                    string.Format("{0} is an invalid date format", value.AttemptedValue)
                );
            }
        }

        return base.BindModel(controllerContext, bindingContext);
    }
}

现在,无论您在 web.config (<globalization>元素) 中设置了什么文化或当前线程文化,自定义模型绑定器DisplayFormat在解析可空日期时都将使用属性的日期格式。

于 2012-06-30T09:20:55.317 回答
1

客户端验证问题可能是由于jquery.validate.unobtrusive.min.js中的 MVC 错误(即使在 MVC 5 中),它不接受任何日期/日期时间格式。不幸的是,您必须手动解决它。

我最终的工作解决方案:

$(function () {
    $.validator.methods.date = function (value, element) {
        return this.optional(element) || moment(value, "DD.MM.YYYY", true).isValid();
    }
});

您必须在之前包括:

@Scripts.Render("~/Scripts/jquery-3.1.1.js")
@Scripts.Render("~/Scripts/jquery.validate.min.js")
@Scripts.Render("~/Scripts/jquery.validate.unobtrusive.min.js")
@Scripts.Render("~/Scripts/moment.js")

您可以使用以下方法安装 moment.js:

Install-Package Moment.js
于 2017-03-08T15:57:18.223 回答
0

谢谢达林,对我来说,能够发布到 create 方法,它只有在我将 BindModel 代码修改为:

public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    var displayFormat = bindingContext.ModelMetadata.DisplayFormatString;
    var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

    if (!string.IsNullOrEmpty(displayFormat) && value != null)
    {
        DateTime date;
        displayFormat = displayFormat.Replace("{0:", string.Empty).Replace("}", string.Empty);
        // use the format specified in the DisplayFormat attribute to parse the date
         if (DateTime.TryParse(value.AttemptedValue, CultureInfo.GetCultureInfo("en-GB"), DateTimeStyles.None, out date))
        {
            return date;
        }
        else
        {
            bindingContext.ModelState.AddModelError(
                bindingContext.ModelName,
                string.Format("{0} is an invalid date format", value.AttemptedValue)
            );
        }
    }

    return base.BindModel(controllerContext, bindingContext);
}

希望这可以帮助别人......

于 2016-08-11T08:56:16.220 回答