Asp.net-MVC는 이제 DateTime 객체의 암시 적 바인딩을 허용합니다. 나는 라인을 따라 행동한다
public ActionResult DoSomething(DateTime startDate)
{
...
}
성공적으로 문자열을 ajax 호출에서 DateTime으로 변환합니다. 그러나 날짜 형식 dd / MM / yyyy를 사용합니다. MVC가 MM / dd / yyyy로 변환 중입니다. 예를 들어 문자열이 ’09 / 02 / 2009 ‘인 액션에 대한 호출을 제출하면 DateTime이 ’02 / 09 / 2009 00:00:00’이거나 로컬 설정에서 9 월 2 일이됩니다.
날짜 형식을 위해 자체 모델 바인더를 롤링하고 싶지 않습니다. 그러나 MVC가 나를 위해이 작업을 수행 할 수 있으면 문자열을 수락하고 DateTime.Parse를 사용하도록 작업을 변경해야 할 필요가없는 것 같습니다.
DateTime의 기본 모델 바인더에 사용되는 날짜 형식을 변경하는 방법이 있습니까? 기본 모델 바인더가 현지화 설정을 사용해서는 안됩니까?
답변
방금 더 철저한 인터넷 검색으로 이에 대한 답을 찾았습니다.
Melvyn Harbor는 MVC가 날짜와 작동하는 방식과 필요한 경우이를 무시할 수있는 방법에 대한 철저한 설명을 제공합니다.
http://weblogs.asp.net/melvynharbour/archive/2008/11/21/mvc-modelbinder-and-localization.aspx
구문 분석 할 값을 찾을 때 프레임 워크는 특정 순서 즉, 다음을 찾습니다.
- RouteData (위에 표시되지 않음)
- URI 쿼리 문자열
- 요청 양식
그러나 이들 중 마지막 만이 문화를 인식 할 것입니다. 현지화 관점에서 볼 때 매우 좋은 이유가 있습니다. 온라인으로 발행 한 항공사 항공편 정보를 보여주는 웹 응용 프로그램을 작성했다고 가정하십시오. 해당 날짜의 링크 (예 : http://www.melsflighttimes.com/Flights/2008-11-21 ) 를 클릭하여 특정 날짜의 항공편을 찾은 다음 해당 동료에게 해당 링크를 이메일로 보내려고합니다. 미국. InvariantCulture를 사용하는 경우 동일한 데이터 페이지를 모두 볼 수있는 유일한 방법입니다. 반대로, 항공편을 예약하기 위해 양식을 사용하는 경우 모든 과정이 빡빡하게 진행됩니다. 데이터는 양식에 기록 될 때 CurrentCulture를 존중할 수 있으므로 양식에서 돌아올 때이를 존중해야합니다.
답변
전 세계적으로 문화를 설정하겠습니다. ModelBinder가 그것을 픽업!
<system.web>
<globalization uiCulture="en-AU" culture="en-AU" />
또는이 페이지에 대해 이것을 변경하십시오.
그러나 전 세계적으로 web.config에서는 더 나은 것으로 생각합니다.
답변
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
답변
MVC 3에서는 약간 다를 것입니다.
Get 메소드를 가진 컨트롤러와 뷰가 있다고 가정하자
public ActionResult DoSomething(DateTime dateTime)
{
return View();
}
ModelBinder를 추가해야합니다
public class DateTimeBinder : IModelBinder
{
#region IModelBinder Members
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
DateTime dateTime;
if (DateTime.TryParse(controllerContext.HttpContext.Request.QueryString["dateTime"], CultureInfo.GetCultureInfo("en-GB"), DateTimeStyles.None, out dateTime))
return dateTime;
//else
return new DateTime();//or another appropriate default ;
}
#endregion
}
Global.asax의 Application_Start () 명령
ModelBinders.Binders.Add(typeof(DateTime), new DateTimeBinder());
답변
자신 만의 모델 바인더를 만들지 않아도 여러 다른 형식을 구문 분석 할 수 있다는 점도 주목할 가치가 있습니다.
예를 들어 미국에서는 다음 문자열이 모두 동일하며 자동으로 동일한 DateTime 값에 바인딩됩니다 .
/ company / press / may % 2001 % 202008
/ company / press / 2008-05-01
/ company / press / 05-01-2008
이식성이 훨씬 뛰어나 yyyy-mm-dd를 사용하는 것이 좋습니다. 현지화 된 여러 형식을 처리하는 것을 정말로 원하지 않습니다. 누군가 1 월 5 일 대신 5 월 1 일에 항공편을 예약하면 큰 문제가 생길 것입니다!
NB : yyyy-mm-dd가 모든 문화권에서 보편적으로 파싱되어 있다면 아는 사람이 의견을 추가 할 수 있는지 여부는 확실하지 않습니다.
답변
toISOString ()을 사용해보십시오. ISO8601 형식의 문자열을 반환합니다.
GET 방법
자바 스크립트
$.get('/example/doGet?date=' + new Date().toISOString(), function (result) {
console.log(result);
});
씨#
[HttpGet]
public JsonResult DoGet(DateTime date)
{
return Json(date.ToString(), JsonRequestBehavior.AllowGet);
}
POST 방법
자바 스크립트
$.post('/example/do', { date: date.toISOString() }, function (result) {
console.log(result);
});
씨#
[HttpPost]
public JsonResult Do(DateTime date)
{
return Json(date.ToString());
}
답변
MVC4에서 아래 구성을 설정했으며 매력처럼 작동합니다.
<globalization uiCulture="auto" culture="auto" />