我一直在模型实体上实现 IValidatableObject ,并使用验证(ValidationContext)来执行验证,通常很复杂。
我可以使用 ValidationContext 来区分不同的验证场景吗?
e.g。以用户模型为例,我有3个验证场景:
这是否正确使用它,如果是这样如何我确保在帖子之后和调用Validate()之前设置正确的ValidationContext属性?或者我应该采取完全不同的方法吗?
答案 0 :(得分:1)
对于我的两分钱,我会说你的模型处于有效状态(应用所有验证标准)或者不是。如果在某些情况下,您不想应用验证,那么我认为您应该使用单独的模型(实际上是ViewModel)。
在您的示例中,我会为注册创建RegisterViewModel
,并为更改详细信息创建单独的EditUserViewModel
。然后,每个都有自己的验证,他们将有一个single responsibility。
创建一个在许多不同视图中重用的胖模型,imho,有点代码味道。我有很多理由想这个。首先,假设您有一个模型用于与用户数据的所有交互。它看起来像这样:
public class UserModel
{
public int UserId { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public bool IsAdministrator { get; set; }
}
稍后您决定跟踪在注册网站期间使用的浏览器。你在哪里添加?它实际上与用户无关,因此不应该使用UserModel
模型。如果您有一个单独的RegisterViewModel
,则可以在注册过程发生变化时根据需要对其进行修改,而不必考虑它将如何影响其使用的其他位置。
如果您将上述模型与MVC的DefaultModelBinder一起使用,则会出现更严重的问题。如上所述here,即使您在表单上没有IsAdministrator
字段(通过利用批量分配漏洞),用户也可以创建自己的请求并授予自己管理员权限。同样,如果使用单独的ViewModel而没有IsAdministrator
属性,则会减少安全漏洞的表面积。
上面只是一个例子,但我相信你明白了。
答案 1 :(得分:1)
IValidatableObject
用于对单个模型执行多次验证。在您的情况下,您拥有User
模型,并且您希望进行三次验证,并且您可以通过在IValidatableObject
模型中实施User
来完美地完成此操作。
ValidationContext
并没有带来太多好处(除了提供对上下文的访问权限),因为我们可以直接在Validate
方法中访问所有属性。
通过IValidatableObject
执行与单个模型相关的多个验证的示例。 (那么ValidationContext
在这里的用途是什么?)
public class Party : IValidatableObject
{
[Required(ErrorMessage = "Start date is required")]
[FutureDateValidator(ErrorMessage = "Start date should be a future date")]
public DateTime StartDate { get; set; }
[Required(ErrorMessage = "Duration is required")]
public int DurationInHours { get; set; }
[Required(ErrorMessage = "No. of joinees is required")]
[Range(2, 10, ErrorMessage = "No. of joinees should be minimum 2 and not more than 10")]
public int NoOfJoinees { get; set; }
public bool Drinks { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (StartDate.TimeOfDay > new TimeSpan(22 - DurationInHours, 0, 0))
{
yield return new ValidationResult("The party should not exceed after 10.00 PM");
}
if (NoOfJoinees < 5 && Drinks)
{
yield return new ValidationResult("Drinks are only allowed if no. of joinees is 5 or more.");
}
}
}