У меня есть маленькое приложение MVC2, которое отображается в двух культурах: en-США и es-MX. Одна часть содержит ввод данных пользователем для даты, которая предварительно заполняется с текущей датой в Модели.
При использовании en-США поле даты отображено как MM/dd/yyyy и может быть изменено с помощью того же формата, не вызывая ошибок проверки.
При использовании es-MX поле даты отображено как dd/MM/yyyy, но когда дата редактируется в этом формате, сбоях проверки серверной стороны с сообщением:
Значение '17/05/1991' не допустимо для Даты.
Одна из первых вещей, которая выскакивает во мне о том сообщении, - то, что оно не локализуется. Оба само сообщение (который я не думаю, что могу управлять) и Отображаемое имя поля (которым я могу управлять и локализуюсь в моем коде). Должен отображаться в локализованном формате.
Я попытался ступить через код для наблюдения точно, где проверка перестала работать, но это, кажется, происходит в некоторых скомпилированных MVC или коде DataAnnotations, который я не вижу.
Детали приложения: IIS6, ASP.NET 3.5 (C#), MVC 2 RTM
Код демонстрационной модели:
public class TestVieModel{
[LocalizedDisplayNameDisplayName("TheDateDisplayName", NameResourceType=typeof(Resources.Model.TestViewModel))]
[Required(ErrorMessageResourceName="TheDateValidationMessageRequired", ErrorMessageResourceType=typeof(Resources.Model.TestViewModel))]
[DataType(DataType.Date)]
public DateTime TheDate { get; set; }
}
Демонстрационный код действия контроллера:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Save(TestViewModel model) {
if(ModelState.IsValid) { // <--- Always is false when using es-MX and a date foramtted as dd/MM/yyyy.
// Do other stuff
return this.View("Complete", model);
}
// Validation failed, redisplay the form.
return this.View("Enter", model);
}
Демонстрационный код представления:
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<HispanicSweeps.Web.Model.LosMets.EnterViewModel>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Test</title>
</head>
<body>
<% using (Html.BeginForm()) {%>
<%= Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%= Html.LabelFor(model => model.TheDate) %>
</div>
<div class="editor-field">
<%= Html.EditorFor(model => model.TheDate) %>
<%= Html.ValidationMessageFor(model => model.TheDate) %>
</div>
<p><input type="submit" value="Save" /></p>
</fieldset>
<% } %>
</body>
</html>
Проверка выполняется в классе DataAnnotations. Вы можете создавать подклассы классов DataAnnotations для своих целей.
Я бы создал новый класс MultiCultureDateType
DataAnnotations, который будет проверять даты в разных культурах.
Дополнительная информация: http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx
Вот как я решил проблему в моем случае. Я вручную проверил дату в контроллере и сбросил ModelState для этого свойства:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Save(TestViewModel model) {
var tempDate = new DateTime();
var culture = CultureInfo.CurrentUICulture;
if(DateTime.TryParse(Request.Form["TheDate"], culture, DateTimeStyles.None, out tempDate)) {
model.DateOfBirth = tempDate;
ModelState.Remove("TheDate");
}
if(ModelState.IsValid) { // <--- Now valid
// Do other stuff
return this.View("Complete", model);
}
// Validation failed, redisplay the form.
return this.View("Enter", model);
}