IValidatableObject Метод Validate срабатывает при сбое DataAnnotations

У меня 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) }

8
задан Community 23 May 2017 в 12:25
поделиться