【问题标题】:Array must contain 1 element数组必须包含 1 个元素
【发布时间】:2012-11-13 13:25:18
【问题描述】:

我有以下课程:

public class CreateJob
{
    [Required]
    public int JobTypeId { get; set; }
    public string RequestedBy { get; set; }
    public JobTask[] TaskDescriptions { get; set; }
}

我想在TaskDescriptions 上方添加一个数据注释,以便数组必须至少包含一个元素?很像[Required]。这可能吗?

【问题讨论】:

    标签: c# .net asp.net-mvc asp.net-mvc-3 model-validation


    【解决方案1】:

    可以使用标准的 Required 和 MinLength 验证属性来完成,但仅适用于数组:

    public class CreateJob
    {
        [Required]
        public int JobTypeId { get; set; }
        public string RequestedBy { get; set; }
        [Required, MinLength(1)]
        public JobTask[] TaskDescriptions { get; set; }
    }
    

    【讨论】:

    • 显然也只有available in .net 4.5+。 :-(
    • 有关此属性的更多信息:您应该将 [Required] 与 [MinLength(1)] 结合使用,因为如果数组为 null(非空,null),则不会触发 MinLength。同样重要的是要注意,默认客户端验证器不支持(如果我错了,请纠正我)。它只会触发 ModelState.IsValid。
    • 该属性也适用于实现 ICollection 接口和字符串的对象。
    • 您应该将@Pluc 的评论添加到您的答案中。拥有 [Required] 属性会使您的答案比上面接受的答案更好。
    • [MinLength(1)] 在 ASP.NET Core 中与 IEnumerable<T> 配合使用
    【解决方案2】:

    我以前见过一个用于此的自定义验证属性,如下所示:

    (我给出了带有列表的示例,但可以适用于数组,或者您可以使用列表)

    public class MustHaveOneElementAttribute : ValidationAttribute
    {
        public override bool IsValid(object value)
        {
            var list = value as IList;
            if (list != null)
            {
                return list.Count > 0;
            }
            return false;
        }
    }
    
    [MustHaveOneElementAttribute (ErrorMessage = "At least a task is required")]
    public List<Person> TaskDescriptions { get; private set; }
    
    // as of C# 8/9 this could be more elegantly done with     
    public class MustHaveOneElementAttribute : ValidationAttribute
    {
        public override bool IsValid(object value)
        {
            return value is IList {Count: > 0};
        }
    }
    

    感谢Antonio Falcão Jr. 的优雅

    【讨论】:

    • 从 C# 8/9 开始,所有这些代码都可以替换为:return value is IList {Count: &gt; 0};
    【解决方案3】:

    请允许我在 .NET Core 中使用 MinLengthAttribute。

    Microsoft 建议使用从 .NET Core 2.0 开始的 Razor Pages。

    目前,在 PageModel 中的属性上使用 MinLengthAttribute 的验证不起作用:

    [BindProperty]
    [Required]
    [MinLength(1)]
    public IEnumerable<int> SelectedStores { get; set; }
    

    当 SelectedStores.Count() == 0 时,ModelState.IsValid 返回 true。

    使用 .NET Core 2.1 Preview 2 测试。

    【讨论】:

    • MinLength 在 .NET Core 2.2 中似乎无法正常工作(也不适用于数组、IEnumerables、ICollections、IList....)
    • 是的,它似乎在 .NET 5 上也被破坏了。
    • [MinLength(1)] 属性适用于我的要求,即我的 List 中至少有 1 个元素,使用 .NET 6 Blazor。
    【解决方案4】:

    这里是@dove 解决方案的改进版本,它可以处理不同类型的集合,例如 HashSet、List 等...

    public class MustHaveOneElementAttribute : ValidationAttribute
    {
        public override bool IsValid(object value)
        {
            var collection = value as IEnumerable;
            if (collection != null && collection.GetEnumerator().MoveNext())
            {
                return true;
            }
            return false;
        }
    }
    

    【讨论】:

      【解决方案5】:

      你必须使用 2 个标准的注解属性

      public class CreateJob
      {
          [MaxLength(1), MinLength(1)]
          public JobTask[] TaskDescriptions { get; set; }
      }
      

      【讨论】:

        【解决方案6】:

        除了 mynkow 的回答之外,我还添加了将最小计数值传递给属性并生成有意义的失败消息的功能:

        public class MinimumElementsRequiredAttribute : ValidationAttribute
        {
          private readonly int _requiredElements;
        
          public MinimumElementsRequiredAttribute(int requiredElements)
          {
            if (requiredElements < 1)
            {
              throw new ArgumentOutOfRangeException(nameof(requiredElements), "Minimum element count of 1 is required.");
            }
        
            _requiredElements = requiredElements;
          }
        
          protected override ValidationResult IsValid(object value, ValidationContext validationContext)
          {
            if (!(value is IEnumerable enumerable))
            {
              return new ValidationResult($"The {validationContext.DisplayName} field is required.");
            }
        
            int elementCount = 0;
            IEnumerator enumerator = enumerable.GetEnumerator();
            while (enumerator.MoveNext())
            {
              if (enumerator.Current != null && ++elementCount >= _requiredElements)
              {
                return ValidationResult.Success;
              }
            }
        
            return new ValidationResult($"At least {_requiredElements} elements are required for the {validationContext.DisplayName} field.");
          }
        }
        

        像这样使用它:

        public class Dto
        {
          [MinimumElementsRequired(2)]
          public IEnumerable<string> Values { get; set; }
        }
        

        【讨论】:

          【解决方案7】:

          仅更新 Dove (@dove) 对 C# 9 语法的响应:

              public class MustHaveOneElementAttribute : ValidationAttribute
              {
                  public override bool IsValid(object value)
                      => value is IList {Count: > 0};
              }
          

          【讨论】:

            【解决方案8】:

            MinLength 属性认为该值为 null 的值是有效的。因此,只需将模型中的属性初始化为空数组即可。

            MinLength(1, ErrorMessageResourceName = nameof(ValidationErrors.AtLeastOneSelected), ErrorMessageResourceType = typeof(ValidationErrors))]
            int[] SelectedLanguages { get; set; } = new int[0];
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2023-03-18
              • 1970-01-01
              • 2019-02-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-05-02
              相关资源
              最近更新 更多