web-dev-qa-db-fra.com

Formatez datetime dans asp.net mvc 4

Comment puis-je forcer le format de date/heure dans asp.net mvc 4? En mode affichage, il s'affiche comme je le veux, mais dans le modèle d'édition, il ne le fait pas . = "{0: jj/MM/aaaa}" Ce que j'ai essayé:

  • globalisation dans web.config (les deux) avec ma culture et mon uiculture.
  • modification de la culture et de la culture dans application_start ()
  • modelbinder personnalisé pour datetime

Je ne sais pas comment le forcer et je dois entrer la date sous la forme jj/mm/aaaa et non par défaut.

PLUS D'INFO: Mon modèle de vue est comme ça

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

en vue j'utilise @Html.DisplayFor(m=>m.Birth) mais cela fonctionne comme prévu (je vois le formatage) et entrer la date que j'utilise @Html.EditorFor(m=>m.Birth) mais si j'essaie d'entrer quelque chose comme 13/12/2000, c'est échec avec l'erreur qu'il ne s'agit date de validité (12/13/2000 et 2000/12/13 fonctionnent comme prévu, mais j’ai besoin de jj/mm/aaaa).

Le modelbinder personnalisé est appelé dans application_start (), car je ne sais pas où.

En utilisant <globalization/>, j’ai essayé avec culture="ro-RO", uiCulture="ro" et d’autres cultures qui me permettraient de jj/mm/aaaa . J'ai également essayé de le définir par thread dans application_start () (il pour faire ça)


Pour tous qui liront cette question: Il semble que la réponse de Darin Dimitrov fonctionnera aussi longtemps que je n'ai pas de validation client . Une autre approche consiste à utiliser une validation personnalisée incluant la validation côté client . I ' Je suis heureux d’avoir découvert cela avant de recréer l’application complète.

55
amb

Ahhhh, maintenant c'est clair. Vous semblez avoir des problèmes pour rétablir la valeur. Pas avec l'affichage sur la vue. En effet, c'est la faute du classeur de modèle par défaut. Vous pouvez écrire et utiliser un nom personnalisé prenant en compte l'attribut [DisplayFormat] de votre modèle. J'ai illustré un classeur de ce type personnalisé ici: https://stackoverflow.com/a/7836093/29407


Apparemment, certains problèmes persistent. Voici ma configuration complète qui fonctionne parfaitement sur ASP.NET MVC 3 & 4 RC.

Modèle:

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

Manette:

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

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

Vue:

@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>
}

Enregistrement du classeur de modèle personnalisé dans Application_Start:

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

Et le classeur de modèle personnalisé lui-même:

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

Désormais, quelle que soit la culture que vous avez configurée dans votre composant web.config (<globalization>) ou la culture de thread actuelle, le classeur de modèle personnalisé utilisera le format de date de l'attribut DisplayFormat lors de l'analyse de dates nullables.

102
Darin Dimitrov

Des problèmes de validation client peuvent survenir à cause d'un bogue MVC (même dans MVC 5) dans jquery.validate.unobtrusive.min.js qui n'accepte aucun format de date/date/heure}. Malheureusement, vous devez le résoudre manuellement. 

_ {Ma solution finalement opérationnelle)

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

Vous devez inclure avant:

@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")

Vous pouvez installer moment.js en utilisant:

Install-Package Moment.js
1
lukyer

Merci Darin, Pour moi, pouvoir publier dans la méthode create, cela ne fonctionnait qu'après avoir modifié le code BindModel pour:

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

J'espère que cela pourrait aider quelqu'un d'autre ...

0
Bashar Abu Shamaa