У меня ViewModel с некоторыми проверками DataAnnotations, а затем для более сложных проверок реализует IValidatableObject и использует метод Validate.
Я ожидал вот этого поведения: сначала все DataAnnotations, а затем, только если ошибок не было, метод Validate. Как бы то ни было, я узнал, что это не всегда правда. Моя модель просмотра (демонстрационная) имеет три поля: одна строка
, одна десятичная
и одна десятичная?
. Все три свойства имеют только обязательный атрибут. Для строки
и десятичного числа ?
поведение является ожидаемым, но для десятичного числа
, когда оно пусто, Требуемая проверка не выполняется (пока все хорошо) и затем выполняет метод Validate. Если я проверю свойство, его значение будет равно нулю.
Что здесь происходит? Что мне не хватает?
Примечание : Я знаю, что атрибут Required должен проверять, является ли значение нулевым. Поэтому я ожидал, что мне скажут не использовать обязательный атрибут в типах, не допускающих значения NULL (потому что он никогда не сработает), или что каким-то образом атрибут понимает значения POST и отмечает, что поле не было заполнено. В первом случае атрибут не должен срабатывать, а метод Validate должен срабатывать.Во втором случае атрибут должен срабатывать, а метод Validate не должен срабатывать. Но мой результат: срабатывают атрибуты и срабатывает метод Validate.
Вот код (ничего особенного):
Контроллер:
public ActionResult Index()
{
return View(HomeModel.LoadHome());
}
[HttpPost]
public ActionResult Index(HomeViewModel viewModel)
{
try
{
if (ModelState.IsValid)
{
HomeModel.ProcessHome(viewModel);
return RedirectToAction("Index", "Result");
}
}
catch (ApplicationException ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, "Internal error.");
}
return View(viewModel);
}
Модель:
public static HomeViewModel LoadHome()
{
HomeViewModel viewModel = new HomeViewModel();
viewModel.String = string.Empty;
return viewModel;
}
public static void ProcessHome(HomeViewModel viewModel)
{
// Not relevant code
}
ViewModel:
public class HomeViewModel : IValidatableObject
{
[Required(ErrorMessage = "Required {0}")]
[Display(Name = "string")]
public string String { get; set; }
[Required(ErrorMessage = "Required {0}")]
[Display(Name = "decimal")]
public decimal Decimal { get; set; }
[Required(ErrorMessage = "Required {0}")]
[Display(Name = "decimal?")]
public decimal? DecimalNullable { get; set; }
public IEnumerable Validate(ValidationContext validationContext)
{
yield return new ValidationResult("Error from Validate method");
}
}
View:
@model MVCTest1.ViewModels.HomeViewModel
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
@using (Html.BeginForm(null, null, FormMethod.Post))
{
@Html.ValidationSummary()
@Html.TextBoxFor(m => m.Nombre)
@Html.TextBoxFor(m => m.Decimal)
@Html.TextBoxFor(m => m.DecimalNullable)
@Html.HiddenFor(m => m.Accion)
}