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

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

RequiredIf data annotation attribute not now showing error message

问题

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

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

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

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

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

  1. <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:

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

I also add the validation summary for testing purposes:

  1. <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 一起使用的完整源代码。

  1. /// <summary>
  2. /// Provides conditional validation based on related property value.
  3. /// </summary>
  4. [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
  5. public sealed class RequiredIfAttribute : ValidationAttribute
  6. {
  7. #region Properties
  8. /// <summary>
  9. /// Gets or sets the other property name that will be used during validation.
  10. /// </summary>
  11. /// <value>
  12. /// The other property name.
  13. /// </value>
  14. public string OtherProperty { get; private set; }
  15. /// <summary>
  16. /// Gets or sets the display name of the other property.
  17. /// </summary>
  18. /// <value>
  19. /// The display name of the other property.
  20. /// </value>
  21. public string OtherPropertyDisplayName { get; set; }
  22. /// <summary>
  23. /// Gets or sets the other property value that will be relevant for validation.
  24. /// </summary>
  25. /// <value>
  26. /// The other property value.
  27. /// </value>
  28. public object OtherPropertyValue { get; private set; }
  29. /// <summary>
  30. /// Gets or sets a value indicating whether other property's value should match or differ from provided other property's value (default is false).
  31. /// </summary>
  32. /// <value>
  33. /// true if other property's value validation should be inverted; otherwise, false.
  34. /// </value>
  35. /// <remarks>
  36. /// How this works
  37. /// - true: validated property is required when other property doesn't equal provided value
  38. /// - false: validated property is required when other property matches provided value
  39. /// </remarks>
  40. public bool IsInverted { get; set; }
  41. /// <summary>
  42. /// Gets a value that indicates whether the attribute requires validation context.
  43. /// </summary>
  44. /// <returns>true if the attribute requires validation context; otherwise, false.</returns>
  45. public override bool RequiresValidationContext => true;
  46. #endregion
  47. #region Constructor
  48. /// <summary>
  49. /// Initializes a new instance of the <see cref="RequiredIfAttribute"/> class.
  50. /// </summary>
  51. /// <param name="otherProperty">The other property.</param>
  52. /// <param name="otherPropertyValue">The other property value.</param>
  53. public RequiredIfAttribute(string otherProperty, object otherPropertyValue)
  54. : base("'{0}' is required because '{1}' has a value {3}'{2}'.")
  55. {
  56. this.OtherProperty = otherProperty;
  57. this.OtherPropertyValue = otherPropertyValue;
  58. this.IsInverted = false;
  59. }
  60. #endregion
  61. /// <summary>
  62. /// Applies formatting to an error message, based on the data field where the error occurred.
  63. /// </summary>
  64. /// <param name="name">The name to include in the formatted message.</param>
  65. /// <returns>
  66. /// An instance of the formatted error message.
  67. /// </returns>
  68. public override string FormatErrorMessage(string name)
  69. {
  70. return string.Format(
  71. CultureInfo.CurrentCulture,
  72. base.ErrorMessageString,
  73. name,
  74. this.OtherPropertyDisplayName ?? this.OtherProperty,
  75. this.OtherPropertyValue,
  76. this.IsInverted ? "other than " : "of ");
  77. }
  78. /// <summary>
  79. /// Validates the specified value with respect to the current validation attribute.
  80. /// </summary>
  81. /// <param name="value">The value to validate.</param>
  82. /// <param name="validationContext">The context information about the validation operation.</param>
  83. /// <returns>
  84. /// An instance of the <see cref="T:System.ComponentModel.DataAnnotations.ValidationResult" /> class.
  85. /// </returns>
  86. protected override ValidationResult IsValid(object value, ValidationContext validationContext)
  87. {
  88. if (validationContext == null)
  89. {
  90. throw new ArgumentNullException(nameof(validationContext));
  91. }
  92. var otherProperty = validationContext.ObjectType.GetProperty(this.OtherProperty);
  93. if (otherProperty == null)
  94. {
  95. return new ValidationResult(
  96. string.Format(CultureInfo.CurrentCulture, "Could not find a property named '{0}'.", this.OtherProperty));
  97. }
  98. var otherValue = otherProperty.GetValue(validationContext.ObjectInstance);
  99. // Check if this value is actually required and validate it
  100. if (!this.IsInverted && object.Equals(otherValue, this.OtherPropertyValue) ||
  101. this.IsInverted && !object.Equals(otherValue, this.OtherPropertyValue))
  102. {
  103. if (value == null)
  104. {
  105. return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName),
  106. new[] { validationContext.MemberName });
  107. }
  108. // Additional check for strings so they're not empty
  109. var val = value as string;
  110. if (val != null && val.Trim().Length == 0)
  111. {
  112. return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName),
  113. new[] { validationContext.MemberName });
  114. }
  115. }
  116. return ValidationResult.Success;
  117. }
  118. }

希望这有助于您的项目!

英文:

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.

  1. /// &lt;summary&gt;
  2. /// Provides conditional validation based on related property value.
  3. /// &lt;/summary&gt;
  4. [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
  5. public sealed class RequiredIfAttribute : ValidationAttribute
  6. {
  7. #region Properties
  8. /// &lt;summary&gt;
  9. /// Gets or sets the other property name that will be used during validation.
  10. /// &lt;/summary&gt;
  11. /// &lt;value&gt;
  12. /// The other property name.
  13. /// &lt;/value&gt;
  14. public string OtherProperty { get; private set; }
  15. /// &lt;summary&gt;
  16. /// Gets or sets the display name of the other property.
  17. /// &lt;/summary&gt;
  18. /// &lt;value&gt;
  19. /// The display name of the other property.
  20. /// &lt;/value&gt;
  21. public string OtherPropertyDisplayName { get; set; }
  22. /// &lt;summary&gt;
  23. /// Gets or sets the other property value that will be relevant for validation.
  24. /// &lt;/summary&gt;
  25. /// &lt;value&gt;
  26. /// The other property value.
  27. /// &lt;/value&gt;
  28. public object OtherPropertyValue { get; private set; }
  29. /// &lt;summary&gt;
  30. /// 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;).
  31. /// &lt;/summary&gt;
  32. /// &lt;value&gt;
  33. /// &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;.
  34. /// &lt;/value&gt;
  35. /// &lt;remarks&gt;
  36. /// How this works
  37. /// - true: validated property is required when other property doesn&#39;t equal provided value
  38. /// - false: validated property is required when other property matches provided value
  39. /// &lt;/remarks&gt;
  40. public bool IsInverted { get; set; }
  41. /// &lt;summary&gt;
  42. /// Gets a value that indicates whether the attribute requires validation context.
  43. /// &lt;/summary&gt;
  44. /// &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;
  45. public override bool RequiresValidationContext =&gt; true;
  46. #endregion
  47. #region Constructor
  48. /// &lt;summary&gt;
  49. /// Initializes a new instance of the &lt;see cref=&quot;RequiredIfAttribute&quot;/&gt; class.
  50. /// &lt;/summary&gt;
  51. /// &lt;param name=&quot;otherProperty&quot;&gt;The other property.&lt;/param&gt;
  52. /// &lt;param name=&quot;otherPropertyValue&quot;&gt;The other property value.&lt;/param&gt;
  53. public RequiredIfAttribute(string otherProperty, object otherPropertyValue)
  54. : base(&quot;&#39;{0}&#39; is required because &#39;{1}&#39; has a value {3}&#39;{2}&#39;.&quot;)
  55. {
  56. this.OtherProperty = otherProperty;
  57. this.OtherPropertyValue = otherPropertyValue;
  58. this.IsInverted = false;
  59. }
  60. #endregion
  61. /// &lt;summary&gt;
  62. /// Applies formatting to an error message, based on the data field where the error occurred.
  63. /// &lt;/summary&gt;
  64. /// &lt;param name=&quot;name&quot;&gt;The name to include in the formatted message.&lt;/param&gt;
  65. /// &lt;returns&gt;
  66. /// An instance of the formatted error message.
  67. /// &lt;/returns&gt;
  68. public override string FormatErrorMessage(string name)
  69. {
  70. return string.Format(
  71. CultureInfo.CurrentCulture,
  72. base.ErrorMessageString,
  73. name,
  74. this.OtherPropertyDisplayName ?? this.OtherProperty,
  75. this.OtherPropertyValue,
  76. this.IsInverted ? &quot;other than &quot; : &quot;of &quot;);
  77. }
  78. /// &lt;summary&gt;
  79. /// Validates the specified value with respect to the current validation attribute.
  80. /// &lt;/summary&gt;
  81. /// &lt;param name=&quot;value&quot;&gt;The value to validate.&lt;/param&gt;
  82. /// &lt;param name=&quot;validationContext&quot;&gt;The context information about the validation operation.&lt;/param&gt;
  83. /// &lt;returns&gt;
  84. /// An instance of the &lt;see cref=&quot;T:System.ComponentModel.DataAnnotations.ValidationResult&quot; /&gt; class.
  85. /// &lt;/returns&gt;
  86. protected override ValidationResult IsValid(object value, ValidationContext validationContext)
  87. {
  88. if (validationContext == null)
  89. {
  90. throw new ArgumentNullException(nameof(validationContext));
  91. }
  92. var otherProperty = validationContext.ObjectType.GetProperty(this.OtherProperty);
  93. if (otherProperty == null)
  94. {
  95. return new ValidationResult(
  96. string.Format(CultureInfo.CurrentCulture, &quot;Could not find a property named &#39;{0}&#39;.&quot;, this.OtherProperty));
  97. }
  98. var otherValue = otherProperty.GetValue(validationContext.ObjectInstance);
  99. //Check if this value is actually required and validate it
  100. if (!this.IsInverted &amp;&amp; object.Equals(otherValue, this.OtherPropertyValue) ||
  101. this.IsInverted &amp;&amp; !object.Equals(otherValue, this.OtherPropertyValue))
  102. {
  103. if (value == null)
  104. {
  105. return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName),
  106. new[] { validationContext.MemberName });
  107. }
  108. //Additional check for strings so they&#39;re not empty
  109. var val = value as string;
  110. if (val != null &amp;&amp; val.Trim().Length == 0)
  111. {
  112. return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName),
  113. new[] { validationContext.MemberName });
  114. }
  115. }
  116. return ValidationResult.Success;
  117. }
  118. }

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:

确定