ASP.NET MVC Условная проверка

Как использовать аннотации данных для условной проверки на модели?

Например, предположим, у нас есть следующая модель (Person и Senior):

public class Person
{
    [Required(ErrorMessage = "*")]
    public string Name
    {
        get;
        set;
    }

    public bool IsSenior
    {
        get;
        set;
    }

    public Senior Senior
    {
        get;
        set;
    }
}

public class Senior
{
    [Required(ErrorMessage = "*")]//this should be conditional validation, based on the "IsSenior" value
    public string Description
    {
        get;
        set;
    }
}

И следующее view:

<%= Html.EditorFor(m => m.Name)%>
<%= Html.ValidationMessageFor(m => m.Name)%>

<%= Html.CheckBoxFor(m => m.IsSenior)%>
<%= Html.ValidationMessageFor(m => m.IsSenior)%>

<%= Html.CheckBoxFor(m => m.Senior.Description)%>
<%= Html.ValidationMessageFor(m => m.Senior.Description)%>

Я хотел бы быть полем условного обязательного свойства "Senior.Description", основанным на выборе свойства IsSenior (true -> обязательный). Как реализовать условную валидацию в ASP.NET MVC 2 с аннотациями данных?

122
задан Andrew Arnold 11 December 2015 в 15:21
поделиться

3 ответа

Я решил эту проблему путем работы со словарем "ModelState", который содержится в контроллере. Словарь ModelState включает в себя все члены, которые должны быть проверены.

Вот решение:

Если вам нужно реализовать условную валидацию на основе некоторого поля (например, если A=true, то B обязательно), сохраняя при этом сообщения об ошибках на уровне свойств (это не относится к пользовательским валидаторам на уровне объектов), вы можете добиться этого, обрабатывая "ModelState", просто удаляя из него ненужные валидации.

...В некотором классе...

public bool PropertyThatRequiredAnotherFieldToBeFilled
{
  get;
  set;
}

[Required(ErrorMessage = "*")] 
public string DepentedProperty
{
  get;
  set;
}

...класс продолжается...

...В некотором действии контроллера ...

if (!PropertyThatRequiredAnotherFieldToBeFilled)
{
   this.ModelState.Remove("DepentedProperty");
}

...

Этим мы добиваемся условной валидации, оставляя все остальное без изменений.


UPDATE:

Это моя окончательная реализация: Я использовал интерфейс на модели и атрибут действия, который проверяет модель, реализующую указанный интерфейс. Интерфейс предписывает метод Validate(ModelStateDictionary modelState). Атрибут action просто вызывает Validate(modelState) на IValidatorSomething.

Я не хотел усложнять этот ответ, поэтому я не упомянул финальные детали реализации (которые, в конце концов, имеют значение в производственном коде).

61
ответ дан 24 November 2019 в 01:21
поделиться

Вам необходимо пройти проверку на уровне Person, а не на уровне Senior, или Senior должен иметь ссылку на своего родительского Person. Мне кажется, что вам нужен механизм самопроверки, который определяет валидацию на человеке, а не на одном из его свойств. Я не уверен, но я не думаю, что DataAnnotations поддерживает это из коробки. Что вы можете сделать, создав свой собственный Атрибут , производный от ValidationAttribute , который можно оформить на уровне класса, а затем создать собственный валидатор, который также позволяет запускать эти валидаторы уровня класса.

Я знаю, что Validation Application Block сразу поддерживает самопроверку, но VAB требует довольно крутого обучения. Тем не менее, вот пример использования VAB:

[HasSelfValidation]
public class Person
{
    public string Name { get; set; }
    public bool IsSenior { get; set; }
    public Senior Senior { get; set; }

    [SelfValidation]
    public void ValidateRange(ValidationResults results)
    {
        if (this.IsSenior && this.Senior != null && 
            string.IsNullOrEmpty(this.Senior.Description))
        {
            results.AddResult(new ValidationResult(
                "A senior description is required", 
                this, "", "", null));
        }
    }
}
3
ответ дан 24 November 2019 в 01:21
поделиться

Вы можете отключить валидаторы условно, удалив ошибки из ModelState:

ModelState["DependentProperty"].Errors.Clear();
17
ответ дан 24 November 2019 в 01:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: