DateTime model özelliklerine kısa tarih biçimi bağlama ile aynı sorunu yaşıyorum. Pek çok farklı örneğe baktıktan sonra (yalnızca DateTime ile ilgili değil) aşağıdaki kanadı bir araya getirdim:
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;
}
}
}
}
Rotaların vb. Global ASAX dosyasında kaydedilme şeklini korumak için, ayrıca CustomModelBinderConfig adlı MVC4 projemin App_Start klasörüne yeni bir sistematik sınıf ekledim:
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());
}
}
}
Daha sonra Global ASASX Application_Start'ımdan statik RegisterCustomModelBinders'ı şöyle çağırıyorum:
protected void Application_Start()
{
/* bla blah bla the usual stuff and then */
CustomModelBindersConfig.RegisterCustomModelBinders();
}
Buradaki önemli bir not şudur: Gizli bir alana böyle bir DateTime değeri yazarsanız:
@Html.HiddenFor(model => model.SomeDate) // a DateTime property
@Html.Hiddenfor(model => model) // a model that is of type DateTime
Bunu yaptım ve sayfadaki gerçek değer istediğim gibi "gg / AA / yyyy ss: dd: ss tt" yerine "AA / gg / yyyy ss: dd: ss tt" biçimindeydi. Bu, model doğrulamamın ya başarısız olmasına ya da yanlış tarihi döndürmesine neden oldu (açıkçası gün ve ay değerlerini değiştiriyor).
Birçok kafa karıştırmadan ve başarısız denemelerden sonra çözüm, Global.ASAX'ta bunu yaparak her istek için kültür bilgisini ayarlamaktı:
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;
}
Bunu Application_Start'a yapıştırırsanız veya hatta Session_Start'a yapıştırırsanız çalışmaz, çünkü bu onu oturumun mevcut iş parçacığına atar. Sizin de bildiğiniz gibi, web uygulamaları devletsizdir, bu nedenle talebinize daha önce hizmet veren iş parçacığı, mevcut isteğinize hizmet eden aynı iş parçacığıdır, bu nedenle kültür bilgileriniz dijital gökyüzündeki harika GC'ye gitmiştir.
Teşekkürler şuraya gidin: 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