如果数据注释属性未显示错误消息,则需要。

huangapple go评论114阅读模式
英文:

RequiredIf data annotation attribute not now showing error message

问题

我使用这个 解决方案 来处理 RequiredIf

逻辑运行正常,会返回带有正确错误消息的 ValidationResult

要显示错误消息,我执行标准操作:

<ValidationMessage For="@(() => Model.Name)"/>

我还添加了验证摘要以进行测试:

<ValidationSummary></ValidationSummary>

然而,错误消息从未显示在输入字段下方。但它确实显示在摘要中。当我将属性更改为标准的 Required 时,错误消息会显示。

我漏掉了什么?

英文:

I use this solution for RequiredIf.

The logic works fine and a ValidationResult with the correct error message is being returned.

To display the error message I do the standard:

<ValidationMessage For="@(() => Model.Name)"/>

I also add the validation summary for testing purposes:

<ValidationSummary></ValidationSummary>

However, the error message is never displayed below the input field. It does however show in the summary. When I change the attribute to the standard Required, then the error message is displayed.

What am I missing?

答案1

得分: 1

这个问题是通过在返回 ValidationResult 时将 MemberName 作为第二个参数添加来解决的。

这是与 Blazor 一起使用的完整源代码。

/// <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 false).
    /// </summary>
    /// <value>
    ///   true if other property's value validation should be inverted; otherwise, false.
    /// </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>true if the attribute requires validation context; otherwise, false.</returns>
    public override bool RequiresValidationContext => 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(nameof(validationContext));
        }

        var 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));
        }

        var 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),
                    new[] { validationContext.MemberName });
            }

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

        return ValidationResult.Success;
    }
}

希望这有助于您的项目!

英文:

The problem was solved by adding the MemberName as the second parameter when returning the ValidationResult.

This is the complete source code which works with Blazor.

/// &lt;summary&gt;
/// Provides conditional validation based on related property value.
/// &lt;/summary&gt;
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class RequiredIfAttribute : ValidationAttribute
{
#region Properties
/// &lt;summary&gt;
/// Gets or sets the other property name that will be used during validation.
/// &lt;/summary&gt;
/// &lt;value&gt;
/// The other property name.
/// &lt;/value&gt;
public string OtherProperty { get; private set; }
/// &lt;summary&gt;
/// Gets or sets the display name of the other property.
/// &lt;/summary&gt;
/// &lt;value&gt;
/// The display name of the other property.
/// &lt;/value&gt;
public string OtherPropertyDisplayName { get; set; }
/// &lt;summary&gt;
/// Gets or sets the other property value that will be relevant for validation.
/// &lt;/summary&gt;
/// &lt;value&gt;
/// The other property value.
/// &lt;/value&gt;
public object OtherPropertyValue { get; private set; }
/// &lt;summary&gt;
/// Gets or sets a value indicating whether other property&#39;s value should match or differ from provided other property&#39;s value (default is &lt;c&gt;false&lt;/c&gt;).
/// &lt;/summary&gt;
/// &lt;value&gt;
///   &lt;c&gt;true&lt;/c&gt; if other property&#39;s value validation should be inverted; otherwise, &lt;c&gt;false&lt;/c&gt;.
/// &lt;/value&gt;
/// &lt;remarks&gt;
/// How this works
/// - true: validated property is required when other property doesn&#39;t equal provided value
/// - false: validated property is required when other property matches provided value
/// &lt;/remarks&gt;
public bool IsInverted { get; set; }
/// &lt;summary&gt;
/// Gets a value that indicates whether the attribute requires validation context.
/// &lt;/summary&gt;
/// &lt;returns&gt;&lt;c&gt;true&lt;/c&gt; if the attribute requires validation context; otherwise, &lt;c&gt;false&lt;/c&gt;.&lt;/returns&gt;
public override bool RequiresValidationContext =&gt; true;
#endregion
#region Constructor
/// &lt;summary&gt;
/// Initializes a new instance of the &lt;see cref=&quot;RequiredIfAttribute&quot;/&gt; class.
/// &lt;/summary&gt;
/// &lt;param name=&quot;otherProperty&quot;&gt;The other property.&lt;/param&gt;
/// &lt;param name=&quot;otherPropertyValue&quot;&gt;The other property value.&lt;/param&gt;
public RequiredIfAttribute(string otherProperty, object otherPropertyValue)
: base(&quot;&#39;{0}&#39; is required because &#39;{1}&#39; has a value {3}&#39;{2}&#39;.&quot;)
{
this.OtherProperty = otherProperty;
this.OtherPropertyValue = otherPropertyValue;
this.IsInverted = false;
}
#endregion
/// &lt;summary&gt;
/// Applies formatting to an error message, based on the data field where the error occurred.
/// &lt;/summary&gt;
/// &lt;param name=&quot;name&quot;&gt;The name to include in the formatted message.&lt;/param&gt;
/// &lt;returns&gt;
/// An instance of the formatted error message.
/// &lt;/returns&gt;
public override string FormatErrorMessage(string name)
{
return string.Format(
CultureInfo.CurrentCulture,
base.ErrorMessageString,
name,
this.OtherPropertyDisplayName ?? this.OtherProperty,
this.OtherPropertyValue,
this.IsInverted ? &quot;other than &quot; : &quot;of &quot;);
}
/// &lt;summary&gt;
/// Validates the specified value with respect to the current validation attribute.
/// &lt;/summary&gt;
/// &lt;param name=&quot;value&quot;&gt;The value to validate.&lt;/param&gt;
/// &lt;param name=&quot;validationContext&quot;&gt;The context information about the validation operation.&lt;/param&gt;
/// &lt;returns&gt;
/// An instance of the &lt;see cref=&quot;T:System.ComponentModel.DataAnnotations.ValidationResult&quot; /&gt; class.
/// &lt;/returns&gt;
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (validationContext == null)
{
throw new ArgumentNullException(nameof(validationContext));
}
var otherProperty = validationContext.ObjectType.GetProperty(this.OtherProperty);
if (otherProperty == null)
{
return new ValidationResult(
string.Format(CultureInfo.CurrentCulture, &quot;Could not find a property named &#39;{0}&#39;.&quot;, this.OtherProperty));
}
var otherValue = otherProperty.GetValue(validationContext.ObjectInstance);
//Check if this value is actually required and validate it
if (!this.IsInverted &amp;&amp; object.Equals(otherValue, this.OtherPropertyValue) ||
this.IsInverted &amp;&amp; !object.Equals(otherValue, this.OtherPropertyValue))
{
if (value == null)
{
return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName), 
new[] { validationContext.MemberName });
}
//Additional check for strings so they&#39;re not empty
var val = value as string;
if (val != null &amp;&amp; val.Trim().Length == 0)
{
return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName), 
new[] { validationContext.MemberName });
}
}
return ValidationResult.Success;
}
}

huangapple
  • 本文由 发表于 2023年6月27日 19:14:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76564285.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定