Saya telah mengalami masalah yang sama dengan format tanggal pendek yang mengikat ke properti model DateTime. Setelah melihat banyak contoh yang berbeda (tidak hanya mengenai DateTime) saya mengumpulkan follwing:
using System;
using System.Globalization;
using System.Web.Mvc;
namespace YourNamespaceHere
{
public class CustomDateBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext", "controllerContext is null.");
if (bindingContext == null)
throw new ArgumentNullException("bindingContext", "bindingContext is null.");
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (value == null)
throw new ArgumentNullException(bindingContext.ModelName);
CultureInfo cultureInf = (CultureInfo)CultureInfo.CurrentCulture.Clone();
cultureInf.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy";
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, value);
try
{
var date = value.ConvertTo(typeof(DateTime), cultureInf);
return date;
}
catch (Exception ex)
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName, ex);
return null;
}
}
}
public class NullableCustomDateBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext", "controllerContext is null.");
if (bindingContext == null)
throw new ArgumentNullException("bindingContext", "bindingContext is null.");
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (value == null) return null;
CultureInfo cultureInf = (CultureInfo)CultureInfo.CurrentCulture.Clone();
cultureInf.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy";
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, value);
try
{
var date = value.ConvertTo(typeof(DateTime), cultureInf);
return date;
}
catch (Exception ex)
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName, ex);
return null;
}
}
}
}
Agar tetap seperti rute dll adalah regiseterd dalam file ASAX Global saya juga menambahkan kelas sytatic baru ke folder App_Start proyek MVC4 saya bernama CustomModelBinderConfig:
using System;
using System.Web.Mvc;
namespace YourNamespaceHere
{
public static class CustomModelBindersConfig
{
public static void RegisterCustomModelBinders()
{
ModelBinders.Binders.Add(typeof(DateTime), new CustomModelBinders.CustomDateBinder());
ModelBinders.Binders.Add(typeof(DateTime?), new CustomModelBinders.NullableCustomDateBinder());
}
}
}
Saya kemudian panggil RegisterCustomModelBinders statis dari Global ASASX Application_Start saya seperti ini:
protected void Application_Start()
{
/* bla blah bla the usual stuff and then */
CustomModelBindersConfig.RegisterCustomModelBinders();
}
Catatan penting di sini adalah jika Anda menulis nilai DateTime ke bidang tersembunyi seperti ini:
@Html.HiddenFor(model => model.SomeDate) // a DateTime property
@Html.Hiddenfor(model => model) // a model that is of type DateTime
Saya melakukan itu dan nilai aktual pada halaman itu dalam format "MM / hh / tttt hh: mm: ss tt" bukan "dd / MM / tttt hh: mm: ss tt" seperti yang saya inginkan. Ini menyebabkan validasi model saya gagal atau mengembalikan tanggal yang salah (jelas menukar nilai hari dan bulan sekitar).
Setelah banyak yang menggaruk-garuk kepala dan upaya yang gagal solusinya adalah mengatur info budaya untuk setiap permintaan dengan melakukan ini di Global.ASAX:
protected void Application_BeginRequest()
{
CultureInfo cInf = new CultureInfo("en-ZA", false);
// NOTE: change the culture name en-ZA to whatever culture suits your needs
cInf.DateTimeFormat.DateSeparator = "/";
cInf.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy";
cInf.DateTimeFormat.LongDatePattern = "dd/MM/yyyy hh:mm:ss tt";
System.Threading.Thread.CurrentThread.CurrentCulture = cInf;
System.Threading.Thread.CurrentThread.CurrentUICulture = cInf;
}
Ini tidak akan berfungsi jika Anda menempelkannya di Application_Start atau bahkan Session_Start karena itu menetapkannya pada utas saat ini untuk sesi. Seperti yang Anda ketahui, aplikasi web tidak memiliki kewarganegaraan sehingga utas yang melayani permintaan Anda sebelumnya adalah utas yang sama untuk melayani permintaan Anda saat ini, maka info kultur Anda telah mencapai GC hebat di langit digital.
Terima kasih buka: Ivan Zlatev - http://ivanz.com/2010/11/03/custom-model-binding-using-imodelbinder-in-asp-net-mvc-two-gotchas/
garik - https://stackoverflow.com/a/2468447/578208
Dmitry - https://stackoverflow.com/a/11903896/578208