Ho avuto lo stesso problema con formato di data breve legame DateTime proprietà modello . Dopo aver guardato molti esempi diversi (non solo per quanto riguarda DateTime) ho messo insieme il 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;
}
}
}
}
Per mantenere con il modo in cui le rotte, ecc sono regiseterd nel file globale ASAX Ho anche aggiunto una nuova classe sytatic al App_Start cartella del mio progetto denominato MVC4 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());
}
}
}
ho poi basta chiamare i RegisterCustomModelBinders statiche dal mio globale ASASX Application_Start come questo:
protected void Application_Start()
{
/* bla blah bla the usual stuff and then */
CustomModelBindersConfig.RegisterCustomModelBinders();
}
Una nota importante è che se si scrive un valore DateTime ad un HiddenField come questo:
@Html.HiddenFor(model => model.SomeDate) // a DateTime property
@Html.Hiddenfor(model => model) // a model that is of type DateTime
ho fatto e il valore effettivo sulla pagina era nel formato "MM hh/gg/aaaa: mm: ss tt "invece di" dd/MM/yyyy hh: mm: ss tt "come volevo. Ciò ha causato il fallimento della mia convalida del modello o il ripristino della data sbagliata (ovviamente invertendo i valori del giorno e del mese).
Dopo un sacco di testa di graffiare e falliti tentativi la soluzione era quella di impostare le informazioni di coltura per ogni richiesta in questo modo nel 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;
}
Non funzionerà se ti infili in Application_Start o anche Session_Start poiché lo assegna al thread corrente per la sessione. Come ben sai, le applicazioni web sono prive di stato, quindi il thread che ha servito la tua richiesta in precedenza non è lo stesso thread che serve la tua richiesta corrente, quindi le informazioni sulla tua cultura sono andate al grande GC nel cielo digitale.
ringraziamenti vanno a: 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
Hey .. Basta cambiare la data di sistema Formato- GG/MM/yyyy a MM/DD/aaaa e fatto. Ho anche lo stesso problema, l'ho risolto modificando il formato della data del sistema. – banny
@banny se l'applicazione è globale e potrebbe essere che nessuno ha lo stesso formato di data, come è possibile farlo? , non supponiamo di andare a cambiare ogni ora Data Formato .. –
Nessuna di queste risposte mi sta aiutando. Il modulo deve essere localizzato. Alcuni utenti possono avere la data in un modo, altri nell'altro modo. Impostazione di qualcosa nel web.config. o global.asax non aiuterà. Continuerò a cercare una risposta migliore, ma un modo sarebbe solo quello di trattare la data come una stringa finché non torno a C#. – astrosteve