【问题标题】:Required attribute for an integer value整数值的必需属性
【发布时间】:2021-07-09 22:01:30
【问题描述】:

我有一个带有 Id 属性的视图模型

[Required]
public int Id { get; set; }

但我认为这个属性只适用于字符串属性。

不设置Id时,Id为0,模型有效。

如果没有为 int 属性设置值,我如何强制执行该模型将无效?

【问题讨论】:

    标签: asp.net-mvc data-annotations


    【解决方案1】:

    使用Range 属性。

    将最小值设置为 1,将最大值设置为 int.MaxValue

    [Range(1, int.MaxValue, ErrorMessage = "Value for {0} must be between {1} and {2}.")]
    

    【讨论】:

    • 是的,但这取决于您的数据库架构。如果您使用从 1 开始的自动递增字段,那么您可能是安全的。我见过的大多数数据库设计都将零视为不可能出现的特殊值。
    • 最佳答案,因为来自客户端的东西是 0,即使它可以为空,它仍然是有效的 int...
    • 不,非常糟糕的做法...您将公认的值限制为> 0,这在当前和/或项目的未来可能不可行...真的不要'不要这样做!
    • @Shockwaver 您的评论与提出的问题无关。另外,您是否建议不验证输入,因为它可能在项目的未来版本中有效??
    • @Shockwaver 请随时发布您出色的答案来启发我们。
    【解决方案2】:

    将类型更改为Nullable<int>(快捷方式int?)以允许null 值。

    【讨论】:

    • 但这不符合逻辑吗?首先,一个不可为空的 int 应该表现得像没有任何必需属性的情况下是必需的。并且可为空的 int 应该表现得像一个非必需值。
    • @user256034 如果零无效,那么您需要一个可为空的 int,因为 Required 只强制存在一个有效的 int 值,其中 0 是有效的。有意义吗?
    • 它不一定是有意义的,它必须是真实的:-)
    • 如果属性是不可为空的外键,那么将其更改为可空的 int 和必需的属性应该无法像在 MVC 中那样验证,太糟糕了它没有
    • 伙计们,这就是模型分层的用途!需要时,您将 DB 实体封装在 ViewModel 中,该 ViewModel 为实际上不能(或不应该)的字段公开可空包装器!然后,在将实体提交到数据库之前,您可以使用 getter 和 setter(或在控制器操作中手动)正确处理实体。 ;)
    【解决方案3】:

    对于 .NET Core(可能还有更早的版本),您还可以创建自定义属性来执行范围验证以便于重用:

    public class Id : ValidationAttribute
    {
        protected override ValidationResult IsValid(
            object value,
            ValidationContext validationContext)
        {
            return Convert.ToInt32(value) > 0 ?
                ValidationResult.Success :
                new ValidationResult($"{validationContext.DisplayName} must be an integer greater than 0.");
        }
    }
    

    在你的模型中使用这样的 Id 属性:

    public class MessageForUpdate
    {
        [Required, Id]
        public int UserId { get; set; }
        [Required]
        public string Text { get; set; }
        [Required, Id]
        public int ChannelId { get; set; }
    }
    

    当 Id 为 <= 0 时返回此错误消息:

    UserId must be an integer greater than 0.

    无需验证该值是否小于 int.MaxValue(尽管在消息中显示该值很好),因为即使该值是 int.MaxValue,API 也会默认在达到此值之前返回此错误+ 1:

    The JSON value could not be converted to System.Int32

    【讨论】:

      【解决方案4】:

      这类似于@Lee Smith 的答案,但允许 0 成为有效输入,这在某些情况下可能很有用。

      您可以做的是将 int 值初始化为另一个值,然后为 0,如下所示:

      [Range(0, int.MaxValue)]
      public int value{ get; set; } = -1;
      

      通过这样做,甚至可以支持除 int.MinValue 之外的所有值:

      [Range(int.MinValue + 1, int.MaxValue)]
      public int value{ get; set; } = int.MinValue;
      

      【讨论】:

        【解决方案5】:

        如果您使用的是数据库,则应使用属性[Key][DatabaseGenerated(DatabaseGenerated.Identity)]Id 不应为NULLABLE

        【讨论】:

          猜你喜欢
          • 2016-01-05
          • 1970-01-01
          • 1970-01-01
          • 2011-03-01
          • 2012-08-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多