MVC4 DataType.Date EditorFor no mostrará el valor de la fecha en Chrome, bien en Internet Explorer

198

Estoy usando el atributo DataType.Date en mi modelo y un EditorFor en mi opinión. Esto funciona bien en Internet Explorer 8 e Internet Explorer 9 , pero en Google Chrome muestra un selector de fecha y en lugar de mostrar el valor, solo muestra "Mes / Día / Año" en texto gris desvaído.

¿Por qué Google Chrome no muestra el valor?

Modelo:

[DataType(DataType.Date)]
public Nullable<System.DateTime> EstPurchaseDate { get; set; }

Ver:

<td class="fieldLabel">Est. Pur. Date</td>
<td class="field">@Html.EditorFor(m=>m.EstPurchaseDate)</td>

Cromo

explorador de Internet

Ben Finkel
fuente

Respuestas:

377

Cuando decora una propiedad de modelo con [DataType(DataType.Date)]la plantilla predeterminada en ASP.NET MVC 4 genera un campo de entrada de type="date":

<input class="text-box single-line" 
       data-val="true" 
       data-val-date="The field EstPurchaseDate must be a date."
       id="EstPurchaseDate" 
       name="EstPurchaseDate" 
       type="date" value="9/28/2012" />

Los navegadores que admiten HTML5, como Google Chrome, representan este campo de entrada con un selector de fecha.

Para mostrar correctamente la fecha, el valor debe formatearse como 2012-09-28. Cita de la especificación :

valor: una fecha completa válida como se define en [RFC 3339], con la calificación adicional de que el componente de año es de cuatro o más dígitos que representan un número mayor que 0.

Puede aplicar este formato utilizando el DisplayFormatatributo:

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public Nullable<System.DateTime> EstPurchaseDate { get; set; }
Darin Dimitrov
fuente
44
Darin gracias, eso fue perfecto! Has respondido a muchas de mis preguntas de MVC en los últimos dos años, ¡eres genial!
Ben Finkel
3
Gran respuesta, pero creo que esto es atractivo, ¡tienes que forzarlo solo para que el control funcione correctamente!
Coops
77
¿Cuál sería la forma de hacer esto "globalmente" para todas las propiedades marcadas [DataType(DataType.Date)]para que no tenga que marcar todas estas propiedades por separado con el riesgo de perder algunas?
Marjan Venema
77
Darin, ¿qué podemos hacer nosotros fuera de Estados Unidos? ¿Cómo puedo establecer el valor de especificación pero mostrar un formato de fecha personalizado? es decir, Reino Unido?
Piotr Kula
3
@ MarjanVenema: he utilizado el "ExtensibleModelMetadataProvider" de FailTracker de Matt Honeycutt ( github.com/MattHoneycutt/Fail-Tracker ). Mire debajo de la Carpeta de Infraestructura a ModelMetadata. Usé esas clases y luego creé una implementación de filtro de IModelMetadataFilter. Cuando se llama al método TransformMetadata, puede editar las propiedades "DisplayFormatString" y "EditFormatString" de los metadatos. Espero que esto te lleve en la dirección correcta (por cierto, hay un gran video en plural que usa Fail-Tracker)
SwampyFox
44

En MVC5.2, agregue Date.cshtml a la carpeta ~ / Views / Shared / EditorTemplates:

@model DateTime?
@{
    IDictionary<string, object> htmlAttributes;
    object objAttributes;
    if (ViewData.TryGetValue("htmlAttributes", out objAttributes))
    {
        htmlAttributes = objAttributes as IDictionary<string, object> ?? HtmlHelper.AnonymousObjectToHtmlAttributes(objAttributes);
    }
    else
    {
        htmlAttributes = new RouteValueDictionary();
    }
    htmlAttributes.Add("type", "date");
    String format = (Request.UserAgent != null && Request.UserAgent.Contains("Chrome")) ? "{0:yyyy-MM-dd}" : "{0:d}";
    @Html.TextBox("", Model, format, htmlAttributes)
}
Charlie
fuente
¡Gracias! soluciona el "problema" de Chrome mencionado y, por supuesto, puede tener otro formato de visualización en su propiedad de fecha y hora.
cmxl
Si gran solución. Esto proporciona un excelente trabajo para aquellos de nosotros que no estamos en los Estados Unidos.
Richard McKenna
Creo que esta es la mejor solución al problema, soluciona solo el problema del editor y no afecta el formato de visualización existente.
dsghi
1
¡Usar "Date.cshtml" en lugar de "DateTime.cshtml" fue la respuesta mágica! Funciona en MVC 4 también.
Atron Seige
¡Excelente! Obrigado
Guilherme de Jesus Santos
16

Como una adición a la respuesta de Darin Dimitrov:

Si solo desea que esta línea en particular use un formato determinado (diferente del estándar), puede usarlo en MVC5:

@Html.EditorFor(model => model.Property, new {htmlAttributes = new {@Value = @Model.Property.ToString("yyyy-MM-dd"), @class = "customclass" } })
Arjan
fuente
Como hay @al principio, que @Value = @Model.Property...todavía necesita eso @? ¿Te refieres a justo new { Value = Model.Property...?
user3454439
11

En MVC 3 tuve que agregar:

using System.ComponentModel.DataAnnotations;

Entre los usos al agregar propiedades:

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

Especialmente si agrega estas propiedades en un archivo .edmx como yo. Descubrí que, de manera predeterminada, los archivos .edmx no lo usan, por lo que agregar solo propiedades no es suficiente.

Azoro
fuente
10

Si elimina [DataType(DataType.Date)]de su modelo, el campo de entrada en Chrome se representa como type="datetime"y tampoco mostrará el selector de fecha.

bernieb
fuente
Gracias Bernie No tuve tantos problemas con el selector que aparecía como con los datos que no se pusieron en el cuadro de entrada. Sin embargo, es bueno saberlo.
Ben Finkel
Sin embargo, Opera presenta un selector de fechas. Use modernizr para hacer un polyfill
cleftheris
1
Si se supone que es una fecha, debe representarse como una entrada de tipo date. Usarlo datetimecomo una solución alternativa es inapropiado, ya que no representa semánticamente los datos.
Chris Pratt
4

Todavía tenía un problema al pasar el formato aaaa-MM-dd, pero lo solucioné cambiando el Date.cshtml:

@model DateTime?

@{
    string date = string.Empty;
    if (Model != null)
    {
        date = string.Format("{0}-{1}-{2}", Model.Value.Year, Model.Value.Month, Model.Value.Day);
    }

    @Html.TextBox(string.Empty, date, new { @class = "datefield", type = "date"  })
}
Markpcasey
fuente
gracias finalmente esto funcionó, traté string.Format("{0}/{1}/{2}")de obtener el dd/mm/yyyyformato, y funciona bien, usé el primer método de base de datos pero DisplayFormat no funcionó con clase parcial, ¿no sé por qué ?, de todos modos, si es necesario, intente este método, no lo hice No lo intente, pero si alguien lo necesita, espero que ayude
Shaijut
3

Responda a MVC4 DataType.Date EditorFor no mostrará el valor de la fecha en Chrome, está bien en IE

En el modelo, debe tener el siguiente tipo de declaración:

[DataType(DataType.Date)]
public DateTime? DateXYZ { get; set; }

O

[DataType(DataType.Date)]
public Nullable<System.DateTime> DateXYZ { get; set; }

No necesita usar el siguiente atributo:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

En Date.cshtml use esta plantilla:

@model Nullable<DateTime>
@using System.Globalization;

@{
    DateTime dt = DateTime.Now;
    if (Model != null)
    {
        dt = (System.DateTime)Model;

    }

    if (Request.Browser.Type.ToUpper().Contains("IE") || Request.Browser.Type.Contains("InternetExplorer"))
    {
        @Html.TextBox("", String.Format("{0:d}", dt.ToShortDateString()), new { @class = "datefield", type = "date" })
    }
    else
    {
        //Tested in chrome
        DateTimeFormatInfo dtfi = CultureInfo.CreateSpecificCulture("en-US").DateTimeFormat;
        dtfi.DateSeparator = "-";
        dtfi.ShortDatePattern = @"yyyy/MM/dd"; 
        @Html.TextBox("", String.Format("{0:d}", dt.ToString("d", dtfi)), new { @class = "datefield", type = "date" })
    } 
}

¡Que te diviertas! Saludos, Blerton

Blerton Hoxha
fuente
Si lo haces de esta manera, Chrome no te dará un selector de fecha. Estoy usando su solución, pero modificando para que 1) SÍ use el DisplayFormatatributo 2) Cambie la prueba para verificar si el tipo de navegador es cromo, luego haga @Html.EditorFor(m=>m.EstPurchaseDate)3) De lo contrario, haga lo siguiente @Html.TextBox("EstPurchaseDate", dt.ToString("MM/dd/yyyy")): en el # 2, una mejor verificación sería si el navegador entiende HTML5, pero no sé cómo hacerlo.
David
44
Downvoting para la detección del navegador en el código del lado del servidor.
Tetsujin no Oni
1

Si necesita tener control sobre el formato de la fecha (en otras palabras, no solo el formato aaaa-mm-dd es aceptable), otra solución podría ser agregar una propiedad auxiliar que sea de tipo cadena y agregar un validador de fecha a esa propiedad y vincular a esta propiedad en la interfaz de usuario.

    [Display(Name = "Due date")]
    [Required]
    [AllowHtml]
    [DateValidation]
    public string DueDateString { get; set; }

    public DateTime? DueDate 
    {
        get
        {
            return string.IsNullOrEmpty(DueDateString) ? (DateTime?)null : DateTime.Parse(DueDateString);
        }
        set
        {
            DueDateString = value == null ? null : value.Value.ToString("d");
        }
    }

Y aquí hay un validador de fechas:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public class DateValidationAttribute : ValidationAttribute
{
    public DateValidationAttribute()
    {
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value != null)
        {
            DateTime date;

            if (value is string)
            {
                if (!DateTime.TryParse((string)value, out date))
                {
                    return new ValidationResult(validationContext.DisplayName + " must be a valid date.");
                }
            }
            else
                date = (DateTime)value;

            if (date < new DateTime(1900, 1, 1) || date > new DateTime(3000, 12, 31))
            {
                return new ValidationResult(validationContext.DisplayName + " must be a valid date.");
            }
        }
        return null;
    }
}
Martin Staufcik
fuente