56 votes

Formatage de la date dans asp.net mvc 4

Comment puis-je forcer le format de la date dans asp.net mvc 4 ? En mode affichage, il s'affiche comme je le souhaite, mais pas en mode édition. J'utilise displayfor et editorfor et applyformatineditmode=true avec dataformatstring="{0:dd/MM/yyyy}". Ce que j'ai essayé :

  • la globalisation dans web.config (les deux) avec ma culture et mon uiculture.
  • modification de la culture et de l'uiculture dans application_start()
  • lien de modèle personnalisé pour datetime

Je n'ai aucune idée de la manière de le forcer et j'ai besoin de saisir la date sous forme de jj/MM/aaaa et non par défaut.

PLUS D'INFO : mon modèle de vue est comme ceci

    [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 pour entrer la date, j'utilise @Html.EditorFor(m=>m.Birth) Mais si j'essaie d'entrer quelque chose comme le 13/12/2000, le message d'erreur suivant s'affiche : ce n'est pas une date valide (le 13/12/2000 et le 13/12/2000 fonctionnent comme prévu, mais j'ai besoin du jour/MM/aaaa).

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

Utilisation de <globalization/> J'ai essayé avec culture="ro-RO", uiCulture="ro" et d'autres cultures qui me donneraient dd/MM/yyyy. J'ai également essayé de le définir sur une base par thread dans application_start() (il y a beaucoup d'exemples ici, sur la façon de le faire).


Pour tous ceux qui liront cette question : Il semble que la réponse de Darin Dimitrov fonctionnera tant que je n'aurai pas de validation côté client. Une autre approche consiste à utiliser une validation personnalisée, y compris une validation côté client. Je suis heureux d'avoir découvert cela avant de recréer l'ensemble de l'application.

102voto

Darin Dimitrov Points 528142

Ahhhh, maintenant c'est clair. Vous semblez avoir des problèmes pour relier la valeur. Pas avec l'affichage de celle-ci sur la vue. En effet, c'est la faute du model binder par défaut. Vous pourriez écrire et utiliser un modèle personnalisé qui prendrait en compte le paramètre [DisplayFormat] sur votre modèle. J'ai illustré un tel classeur de modèle personnalisé ici : http://stackoverflow.com/a/7836093/29407


Apparemment, certains problèmes persistent. Voici ma configuration complète qui fonctionne parfaitement sur ASP.NET MVC 3 et 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; }
}

Contrôleur :

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

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

Voir :

@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 modèle personnalisé de liant dans Application_Start :

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

Et le classeur de modèles personnalisés 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);
    }
}

Maintenant, peu importe la culture que vous avez configurée dans votre web.config ( <globalization> ) ou la culture du fil actuel, le liant de modèle personnalisé utilisera l'élément DisplayFormat le format de date de l'attribut lors de l'analyse des dates non valables.

1voto

lukyer Points 3269

Les problèmes de validation du client peuvent se produire à cause d'un bogue MVC (même dans MVC 5) dans les éléments suivants jquery.validate.unobtrusive.min.js dont n'accepte en aucun cas le format date/datetime . Malheureusement, vous devez le résoudre manuellement.

Ma solution qui fonctionne enfin :

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

Vous devez l'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

0voto

Bashar Abu Shamaa Points 915

Merci Darin, En ce qui me concerne, pour pouvoir envoyer des messages à la méthode create, cela n'a fonctionné qu'après avoir modifié le code BindModel en :

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 pourra aider quelqu'un d'autre...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X