DateTime 모델 속성에 짧은 날짜 형식 바인딩과 동일한 문제가 있습니다. 많은 다른 예제 (DateTime뿐만 아니라)를 본 후에 다음 내용을 정리했습니다.
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;
}
}
}
}
Global ASAX 파일에서 경로 등이 등록되는 방식을 유지하기 위해 CustomModelBinderConfig라는 MVC4 프로젝트의 App_Start 폴더에 새로운 sytatic 클래스를 추가했습니다.
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());
}
}
}
그런 다음 Global ASASX Application_Start에서 정적 RegisterCustomModelBinders를 다음과 같이 호출합니다.
protected void Application_Start()
{
/* bla blah bla the usual stuff and then */
CustomModelBindersConfig.RegisterCustomModelBinders();
}
여기서 중요한 점은 DateTime 값을 숨겨진 필드에 다음과 같이 쓰는 경우입니다.
@Html.HiddenFor(model => model.SomeDate) // a DateTime property
@Html.Hiddenfor(model => model) // a model that is of type DateTime
나는 그것을했고 페이지의 실제 값은 내가 원하는 것처럼 "dd / MM / yyyy hh : mm : ss tt"대신 "MM / dd / yyyy hh : mm : ss tt"형식이었습니다. 이로 인해 내 모델 유효성 검사가 실패하거나 잘못된 날짜를 반환했습니다 (날짜와 월 값을 바꿔 놓음).
많은 헤드 스크래치와 실패한 시도 후에 솔루션은 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;
}
Application_Start 또는 Session_Start에 고정하면 세션의 현재 스레드에 할당되므로 작동하지 않습니다. 아시다시피, 웹 응용 프로그램은 상태가 없으므로 이전 요청을 처리 한 스레드는 현재 요청을 처리하는 스레드와 동일하므로 문화 정보가 디지털 하늘의 위대한 GC로 이동했습니다.
감사합니다 : 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
드미트리-https: //stackoverflow.com/a/11903896/578208