web-dev-qa-db-ja.com

データ注釈を使用した条件付き必須プロパティ

私はこのようなクラスを持っています:

public class Document
{
   public int DocumentType{get;set;}

   [Required]
   public string Name{get;set;}

   [Required]
   public string Name2{get;set;}
}

Nameプロパティと[Required]プロパティにName2データアノテーションを付けると、すべてが問題なく、NameまたはName2が空の場合、検証エラーをスローします。

ただし、Nameが1に等しい場合にのみDocumentTypeフィールドが必要であり、DocumentTypeが2に等しい場合にのみName2が必要です。

public class Document
{
   public int DocumentType{get;set;}

   [Required(Expression<Func<object, bool>>)]
   public string Name{get;set;}

   [Required(Expression<Func<object, bool>>)]
   public string Name2{get;set;}
}

しかし、私はできないことを知っています、それはエラーを引き起こします。この要件に対して何をすべきですか?

51
brtb

箱から出して、これはまだ不可能だと思います。

しかし、私はこれを見つけました Mvc.ValidationToolkitについての有望な記事(また ここ 、残念ながら this はアルファのみで、しかし、おそらくこのコードから必要なメソッドを抽出して独自に統合することもできます)、それはあなたの原因と正確に一致するように見えるニースサウンド属性RequiredIfを含んでいます:

  • linked Zip からプロジェクトをダウンロードしてビルドします
  • ビルドフォルダーからビルドされたdllを取得し、使用しているプロジェクトで参照します
  • 残念ながら、これもMVCへの参照を必要とするようです(VSまたは_install-package Microsoft.AspNet.Mvc_でMVCプロジェクトを開始するのが最も簡単な方法です)
  • 使用するファイルに_using Mvc.ValidationToolkit;_を追加します
  • [RequiredIf("DocumentType", 2)][RequiredIf("DocumentType", 1)]のようなものを書くことができるので、nameが1または2に等しくない限り、DocumentTypeも_name2_も指定されていない場合、オブジェクトは有効です。
6
DrCopyPaste

RequiredIf検証属性

別のプロパティに特定の値がある場合(必要な値)、または別のプロパティにanything but特定の値がある場合、特定のプロパティ値を必要とするRequiredIfAttributeを記述しました。

これは役立つコードです:

/// <summary>
/// Provides conditional validation based on related property value.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class RequiredIfAttribute : ValidationAttribute
{
    #region Properties

    /// <summary>
    /// Gets or sets the other property name that will be used during validation.
    /// </summary>
    /// <value>
    /// The other property name.
    /// </value>
    public string OtherProperty { get; private set; }

    /// <summary>
    /// Gets or sets the display name of the other property.
    /// </summary>
    /// <value>
    /// The display name of the other property.
    /// </value>
    public string OtherPropertyDisplayName { get; set; }

    /// <summary>
    /// Gets or sets the other property value that will be relevant for validation.
    /// </summary>
    /// <value>
    /// The other property value.
    /// </value>
    public object OtherPropertyValue { get; private set; }

    /// <summary>
    /// Gets or sets a value indicating whether other property's value should match or differ from provided other property's value (default is <c>false</c>).
    /// </summary>
    /// <value>
    ///   <c>true</c> if other property's value validation should be inverted; otherwise, <c>false</c>.
    /// </value>
    /// <remarks>
    /// How this works
    /// - true: validated property is required when other property doesn't equal provided value
    /// - false: validated property is required when other property matches provided value
    /// </remarks>
    public bool IsInverted { get; set; }

    /// <summary>
    /// Gets a value that indicates whether the attribute requires validation context.
    /// </summary>
    /// <returns><c>true</c> if the attribute requires validation context; otherwise, <c>false</c>.</returns>
    public override bool RequiresValidationContext
    {
        get { return true; }
    }

    #endregion

    #region Constructor

    /// <summary>
    /// Initializes a new instance of the <see cref="RequiredIfAttribute"/> class.
    /// </summary>
    /// <param name="otherProperty">The other property.</param>
    /// <param name="otherPropertyValue">The other property value.</param>
    public RequiredIfAttribute(string otherProperty, object otherPropertyValue)
        : base("'{0}' is required because '{1}' has a value {3}'{2}'.")
    {
        this.OtherProperty = otherProperty;
        this.OtherPropertyValue = otherPropertyValue;
        this.IsInverted = false;
    }

    #endregion

    /// <summary>
    /// Applies formatting to an error message, based on the data field where the error occurred.
    /// </summary>
    /// <param name="name">The name to include in the formatted message.</param>
    /// <returns>
    /// An instance of the formatted error message.
    /// </returns>
    public override string FormatErrorMessage(string name)
    {
        return string.Format(
            CultureInfo.CurrentCulture,
            base.ErrorMessageString,
            name,
            this.OtherPropertyDisplayName ?? this.OtherProperty,
            this.OtherPropertyValue,
            this.IsInverted ? "other than " : "of ");
    }

    /// <summary>
    /// Validates the specified value with respect to the current validation attribute.
    /// </summary>
    /// <param name="value">The value to validate.</param>
    /// <param name="validationContext">The context information about the validation operation.</param>
    /// <returns>
    /// An instance of the <see cref="T:System.ComponentModel.DataAnnotations.ValidationResult" /> class.
    /// </returns>
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (validationContext == null)
        {
            throw new ArgumentNullException("validationContext");
        }

        PropertyInfo otherProperty = validationContext.ObjectType.GetProperty(this.OtherProperty);
        if (otherProperty == null)
        {
            return new ValidationResult(
                string.Format(CultureInfo.CurrentCulture, "Could not find a property named '{0}'.", this.OtherProperty));
        }

        object otherValue = otherProperty.GetValue(validationContext.ObjectInstance);

        // check if this value is actually required and validate it
        if (!this.IsInverted && object.Equals(otherValue, this.OtherPropertyValue) ||
            this.IsInverted && !object.Equals(otherValue, this.OtherPropertyValue))
        {
            if (value == null)
            {
                return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
            }

            // additional check for strings so they're not empty
            string val = value as string;
            if (val != null && val.Trim().Length == 0)
            {
                return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
            }
        }

        return ValidationResult.Success;
    }
}
74
Robert Koritnik

データ注釈を使用して条件付きで必須のプロパティ

 [RequiredIf(dependent Property name, dependent Property value)]

e.g. 


 [RequiredIf("Country", "Ethiopia")]
 public string POBox{get;set;}
 // POBox is required in Ethiopia
 public string Country{get;set;}

 [RequiredIf("destination", "US")]
 public string State{get;set;}
 // State is required in US

 public string destination{get;set;}



public class RequiredIfAttribute : ValidationAttribute
{
    RequiredAttribute _innerAttribute = new RequiredAttribute();
    public string _dependentProperty { get; set; }
    public object _targetValue { get; set; }

    public RequiredIfAttribute(string dependentProperty, object targetValue)
    {
        this._dependentProperty = dependentProperty;
        this._targetValue = targetValue;
    }
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var field = validationContext.ObjectType.GetProperty(_dependentProperty);
        if (field != null)
        {
            var dependentValue = field.GetValue(validationContext.ObjectInstance, null);
            if ((dependentValue == null && _targetValue == null) || (dependentValue.Equals(_targetValue)))
            {
                if (!_innerAttribute.IsValid(value))
                {
                    string name = validationContext.DisplayName;
                    return new ValidationResult(ErrorMessage=name + " Is required.");
                }
            }
            return ValidationResult.Success;
        }
        else
        {
            return new ValidationResult(FormatErrorMessage(_dependentProperty));
        }
    }
}
20
Ghebrehiywet

Fluent Validationをご覧ください

https://www.nuget.org/packages/FluentValidation/

プロジェクトの説明ビジネスオブジェクトの検証ルールを構築するために、流れるようなインターフェイスとラムダ式を使用する.NET用の小さな検証ライブラリ。

https://github.com/JeremySkinner/FluentValidation

4
Chris McKelt

MVCFoolproof 検証を確認してください。正しく覚えていれば、RequiredIf(依存プロパティ、依存値)のようなモデルにデータ注釈があります。以下からFoolproofをダウンロードできます。
Visual Studio(2017)->ツール-> Nuget Package Manager->ソリューションのNugetパッケージの管理。 jqueryファイルに加えて、mvcfoolproof.unobtrusive.min.jsを参照してください。

1
Jaggan_j

System.ComponentModel.DataAnnotationsから実装されたIValidatableObjectを常に使用しました。

下の例

  public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (this.SendInAppNotification)
            {
                if (string.IsNullOrEmpty(this.NotificationTitle) || string.IsNullOrWhiteSpace(this.NotificationTitle))
                {
                    yield return new ValidationResult(
                        $"Notification Title is required",
                        new[] { nameof(this.NotificationTitle) });
                }
            }
0
chris castle