整数值的必需属性

use*_*034 60 asp.net-mvc data-annotations

我有一个带Id属性的viewmodel

[Required]
public int Id { get; set; }
Run Code Online (Sandbox Code Playgroud)

但我认为这个属性仅适用于字符串属性.

如果未设置Id,则Id的值为0且模型有效.

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

Lee*_*ith 78

使用Range属性.

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

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

  • 没错,但这取决于您的数据库架构.如果您使用从1开始的自动增量字段,那么您可能很安全.我见过的大多数数据库设计都将零视为一种不可能发生的特殊值. (3认同)
  • 不,非常糟糕的做法...您将承认的值限制为“> 0”,这在项目的当前和/或未来可能不可行...真的不要这样做! (3认同)
  • 我会轻轻地忽略你的嘲笑(我知道我有时会成为一根手指)...正如我在上面的评论中所说,不要限制你不能做出假设的范围,而是封装你的ViewModel 中的实体(具有继承或属性项)并使用属性“int?”(具有相关的私有字段),其设置器也写入请求的字段 Id,因此使其保持原始状态。当然,您的 DataAnnotation `[Required]` 位于此包装器道具上。剩下的只是逻辑。没有时间写出完整的正式答案,但我相信您已经理解了。 (3认同)
  • 最好的答案,因为客户端来自0,即使它可以为空,它仍然是有效的... (2认同)

Jul*_*ain 46

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

  • 但这不符合逻辑吗?首先,非可空int应该表现得像没有任何必需属性.并且nullable int应该表现得像一个非必需值. (16认同)
  • @ user256034如果零无效,那么您需要一个可为空的int,因为Required只强制存在一个有效的int值,其中0是有效的.合理? (5认同)
  • 它没有意义,它必须是真的:-) (4认同)
  • 伙计们,这就是模型分层的用途!当需要时,您将数据库实体封装在 ViewModel 中,该视图模型为实际上不能(或不应该)的字段公开可空包装器!然后,在将实体提交到数据库之前,您可以使用 getter 和 setter(或在控制器操作中手动)正确处理实体。;) (2认同)

Dus*_*n C 5

对于 .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.");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

public class MessageForUpdate
{
    [Required, Id]
    public int UserId { get; set; }
    [Required]
    public string Text { get; set; }
    [Required, Id]
    public int ChannelId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

UserId must be an integer greater than 0.

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

The JSON value could not be converted to System.Int32


Dav*_*erg 5

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

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

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

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

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