MVC4 DataType.Date EditorFor tidak akan menampilkan nilai tanggal di Chrome, baik di Internet Explorer

198

Saya menggunakan atribut DataType.Date pada model saya dan EditorFor dalam pandangan saya. Ini berfungsi dengan baik di Internet Explorer 8 dan Internet Explorer 9 , tetapi di Google Chrome ini menunjukkan pemilih tanggal dan bukannya menampilkan nilai itu hanya menampilkan "Bulan / Hari / Tahun" dalam teks abu-abu pudar.

Mengapa Google Chrome tidak menampilkan nilai?

Model:

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

Melihat:

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

Chrome

Internet Explorer

Ben Finkel
sumber

Jawaban:

377

Ketika Anda menghias properti model dengan [DataType(DataType.Date)]templat default di ASP.NET MVC 4 menghasilkan bidang input 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" />

Browser yang mendukung HTML5 seperti Google Chrome membuat bidang input ini dengan pemilih tanggal.

Agar dapat menampilkan tanggal dengan benar, nilai harus diformat sebagai 2012-09-28. Kutipan dari spesifikasi :

nilai: Tanggal penuh yang valid sebagaimana didefinisikan dalam [RFC 3339], dengan kualifikasi tambahan bahwa komponen tahun adalah empat atau lebih digit yang mewakili angka lebih besar dari 0.

Anda dapat menerapkan format ini menggunakan DisplayFormatatribut:

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public Nullable<System.DateTime> EstPurchaseDate { get; set; }
Darin Dimitrov
sumber
44
Darin terima kasih, itu sempurna! Anda telah menjawab begitu banyak pertanyaan MVC saya selama dua tahun terakhir, ya ampun!
Ben Finkel
3
Jawaban yang bagus tetapi saya merasa ini menarik Anda harus memaksanya hanya untuk mendapatkan kontrol untuk bekerja dengan baik!
Coops
7
Apa yang akan menjadi cara melakukan ini "secara global" untuk semua properti yang ditandai [DataType(DataType.Date)]jadi saya tidak perlu menandai semua properti ini secara terpisah dengan risiko kehilangan sebagian?
Marjan Venema
7
Darin, Apa yang bisa kita lakukan di luar AS? Bagaimana saya bisa menetapkan nilai spesifikasi tetapi menampilkan format tanggal khusus? yaitu Inggris?
Piotr Kula
3
@ MarjanVenema- Saya telah menggunakan "ExtensibleModelMetadataProvider" dari FailTracker milik Matt Honeycutt ( github.com/MattHoneycutt/Fail-Tracker ). Lihat di bawah Folder Infrastruktur ke ModelMetadata. Saya telah menggunakan kelas-kelas itu dan kemudian membuat implementasi filter IModelMetadataFilter. Ketika metode TransformMetadata dipanggil, Anda kemudian dapat mengedit properti "DisplayFormatString" dan "EditFormatString" dari metadata. Semoga ini membuat Anda ke arah yang benar (btw, ada video pluralsight besar yang menggunakan Fail-Tracker)
SwampyFox
44

Di MVC5.2, tambahkan Date.cshtml ke folder ~ / 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
sumber
Terima kasih! memperbaiki "masalah" chrome yang disebutkan dan tentu saja Anda dapat memiliki format tampilan lain di properti datetime Anda!
cmxl
Ya solusi bagus. Ini memberikan pekerjaan yang sangat baik bagi kita yang tidak di AS.
Richard McKenna
Saya pikir ini adalah solusi terbaik untuk masalah ini, hanya memperbaiki masalah editor dan tidak memengaruhi pemformatan tampilan yang ada.
dsghi
1
Menggunakan "Date.cshtml" alih-alih "DateTime.cshtml" adalah jawaban ajaib! Ia bekerja di MVC 4 juga.
Atron Seige
Bagus! Obrigado.
Guilherme de Jesus Santos
16

Sebagai tambahan untuk jawaban Darin Dimitrov:

Jika Anda hanya ingin baris khusus ini menggunakan format tertentu (berbeda dari standar), Anda dapat menggunakan di MVC5:

@Html.EditorFor(model => model.Property, new {htmlAttributes = new {@Value = @Model.Property.ToString("yyyy-MM-dd"), @class = "customclass" } })
Arjan
sumber
Seperti ada @di awal, @Value = @Model.Property...masih perlu itu @? Apakah maksud Anda adil new { Value = Model.Property...?
user3454439
11

Di MVC 3 saya harus menambahkan:

using System.ComponentModel.DataAnnotations;

di antara usings saat menambahkan properti:

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

Terutama jika Anda menambahkan properti ini dalam file .edmx seperti saya. Saya menemukan bahwa secara default .edmx file tidak menggunakan ini sehingga menambahkan propeties saja tidak cukup.

Azoro
sumber
10

Jika Anda menghapus [DataType(DataType.Date)]dari model Anda, bidang input di Chrome ditampilkan sebagai type="datetime"dan tidak akan menampilkan datepicker juga.

bernieb
sumber
Bernie terima kasih. Saya tidak begitu kesulitan dengan pemilih muncul karena saya dengan data tidak dimasukkan ke dalam kotak input. Ini bagus untuk diketahui.
Ben Finkel
Opera membuat datepicker. Gunakan modernizr untuk melakukan beberapa polyfill
cleftheris
1
Jika seharusnya tanggal, itu harus diterjemahkan sebagai input tipe date. Menggunakan datetimesebagai solusi tidak tepat, karena tidak secara semantik mewakili data.
Chris Pratt
4

Saya masih memiliki masalah dengan itu meneruskan format yyyy-MM-dd, tapi saya mengatasinya dengan mengubah 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
sumber
terima kasih akhirnya ini berhasil, saya mencoba string.Format("{0}/{1}/{2}")untuk mendapatkan dd/mm/yyyyformat, dan berfungsi dengan baik, saya menggunakan metode database pertama tetapi DisplayFormat tidak bekerja dengan kelas parsial, tidak tahu mengapa ?, lagi pula siapa pun jika perlu mencoba metode ini , saya tidak t coba tetapi jika ada yang membutuhkan, harap ini membantu
shaijut
3

Membalas MVT4 DataType.Date EditorFor tidak akan menampilkan nilai tanggal di Chrome, baik di IE

Dalam Model, Anda harus memiliki jenis deklarasi berikut:

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

ATAU

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

Anda tidak perlu menggunakan atribut berikut:

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

Di Date.cshtml gunakan templat ini:

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

Selamat bersenang-senang! Salam, Blerton

Blerton Hoxha
sumber
Jika Anda melakukannya dengan cara ini, Chrome tidak akan memberi Anda pemilih tanggal. Saya menggunakan solusi Anda, tetapi memodifikasi sehingga 1) Saya DO menggunakan DisplayFormatatribut 2) Ubah tes untuk memeriksa apakah jenis browser krom, lalu lakukan @Html.EditorFor(m=>m.EstPurchaseDate)3) Lain @Html.TextBox("EstPurchaseDate", dt.ToString("MM/dd/yyyy"))Catatan: pada # 2, pemeriksaan yang lebih baik adalah jika browser mengerti HTML5, tapi saya tidak tahu bagaimana melakukannya.
David
4
Downvoting untuk deteksi browser dalam kode sisi server.
Tetsujin no Oni
1

Jika Anda perlu memiliki kontrol atas format tanggal (dengan kata lain bukan hanya format tttt-tttt-tt dapat diterima), solusi lain dapat menambahkan properti pembantu yang bertipe string dan menambahkan validator tanggal ke properti itu , dan ikat ke properti ini di UI.

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

Dan ini adalah validator tanggal:

[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
sumber