Атрибут, зависящий от другого поля

В модели моего приложения ASP.NET MVC я хотел бы проверить текстовое поле как требуется, только если установлен определенный флажок.

Что-то вроде

public bool retired {get, set};

[RequiredIf("retired",true)]
public string retirementAge {get, set};

Как я могу это сделать?

Спасибо.

Ответ 1

Взгляните на это: http://blogs.msdn.com/b/simonince/archive/2010/06/04/conditional-validation-in-mvc.aspx

Я немного модифицировал код в соответствии с моими потребностями. Возможно, вы также пользуетесь этими изменениями.

public class RequiredIfAttribute : ValidationAttribute
{
    private RequiredAttribute innerAttribute = new RequiredAttribute();
    public string DependentUpon { get; set; }
    public object Value { get; set; }

    public RequiredIfAttribute(string dependentUpon, object value)
    {
        this.DependentUpon = dependentUpon;
        this.Value = value;
    }

    public RequiredIfAttribute(string dependentUpon)
    {
        this.DependentUpon = dependentUpon;
        this.Value = null;
    }

    public override bool IsValid(object value)
    {
        return innerAttribute.IsValid(value);
    }
}

public class RequiredIfValidator : DataAnnotationsModelValidator<RequiredIfAttribute>
{
    public RequiredIfValidator(ModelMetadata metadata, ControllerContext context, RequiredIfAttribute attribute)
        : base(metadata, context, attribute)
    { }

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
    {
        // no client validation - I might well blog about this soon!
        return base.GetClientValidationRules();
    }

    public override IEnumerable<ModelValidationResult> Validate(object container)
    {
        // get a reference to the property this validation depends upon
        var field = Metadata.ContainerType.GetProperty(Attribute.DependentUpon);

        if (field != null)
        {
            // get the value of the dependent property
            var value = field.GetValue(container, null);

            // compare the value against the target value
            if ((value != null && Attribute.Value == null) || (value != null && value.Equals(Attribute.Value)))
            {
                // match => means we should try validating this field
                if (!Attribute.IsValid(Metadata.Model))
                    // validation failed - return an error
                    yield return new ModelValidationResult { Message = ErrorMessage };
            }
        }
    }
}

Затем используйте его:

public DateTime? DeptDateTime { get; set; }
[RequiredIf("DeptDateTime")]
public string DeptAirline { get; set; }

Ответ 2

Просто используйте библиотеку проверки подлинности Foolproof, доступную в Codeplex: https://foolproof.codeplex.com/

Он поддерживает, среди прочего, следующие атрибуты/украшения: "requiredif":

[RequiredIf]
[RequiredIfNot]
[RequiredIfTrue]
[RequiredIfFalse]
[RequiredIfEmpty]
[RequiredIfNotEmpty]
[RequiredIfRegExMatch]
[RequiredIfNotRegExMatch]

Для начала легко:

  • Загрузите пакет из предоставленной ссылки
  • Добавить ссылку на файл .dll.
  • Импортируйте включенные файлы javascript
  • Убедитесь, что ваши представления ссылаются на включенные javascript файлы из своего HTML-кода для ненавязчивой проверки javascript и jquery.

Ответ 3

Я не видел ничего из коробки, которая позволила бы вам это сделать.

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Globalization;

namespace System.ComponentModel.DataAnnotations
{
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
    public sealed class RequiredIfAttribute : ValidationAttribute
    {
        private const string _defaultErrorMessage = "'{0}' is required";
        private readonly object _typeId = new object();

        private string  _requiredProperty;
        private string  _targetProperty;
        private bool    _targetPropertyCondition;

        public RequiredIfAttribute(string requiredProperty, string targetProperty, bool targetPropertyCondition)
            : base(_defaultErrorMessage)
        {
            this._requiredProperty          = requiredProperty;
            this._targetProperty            = targetProperty;
            this._targetPropertyCondition   = targetPropertyCondition;
        }

        public override object TypeId
        {
            get
            {
                return _typeId;
            }
        }

        public override string FormatErrorMessage(string name)
        {
            return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString, _requiredProperty, _targetProperty, _targetPropertyCondition);
        }

        public override bool IsValid(object value)
        {
            bool result             = false;
            bool propertyRequired   = false; // Flag to check if the required property is required.

            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
            string requiredPropertyValue            = (string) properties.Find(_requiredProperty, true).GetValue(value);
            bool targetPropertyValue                = (bool) properties.Find(_targetProperty, true).GetValue(value);

            if (targetPropertyValue == _targetPropertyCondition)
            {
                propertyRequired = true;
            }

            if (propertyRequired)
            {
                //check the required property value is not null
                if (requiredPropertyValue != null)
                {
                    result = true;
                }
            }
            else
            {
                //property is not required
                result = true;
            }

            return result;
        }
    }
}

Над вашим классом модели вам просто нужно добавить:

[RequiredIf("retirementAge", "retired", true)]
public class MyModel

В вашем представлении

<%= Html.ValidationSummary() %> 

Должно отображать сообщение об ошибке всякий раз, когда свойство retired имеет значение true и требуемое свойство пусто.

Надеюсь, что это поможет.

Ответ 4

Попробуйте использовать собственный атрибут :

[ConditionalRequired("retired==true")]
public string retirementAge {get, set};

Он поддерживает несколько условий.

Ответ 5

Используя диспетчер пакетов NuGet, я установил следующее: https://github.com/jwaliszko/ExpressiveAnnotations

И это моя модель:

using ExpressiveAnnotations.Attributes;

public bool HasReferenceToNotIncludedFile { get; set; }

[RequiredIf("HasReferenceToNotIncludedFile == true", ErrorMessage = "RelevantAuditOpinionNumbers are required.")]
public string RelevantAuditOpinionNumbers { get; set; }

Я гарантирую, что это сработает!