【发布时间】:2020-05-08 08:43:22
【问题描述】:
我有一个基于 asp.net core 3.1 的项目。我需要添加一个自定义验证规则,该规则需要一个数据库调用才能确定值的有效性。
例如,当创建一个新用户时,我需要在允许创建用户之前验证数据库中没有其他用户名具有相同的用户名。
如果我可以创建自定义属性UniqueUsername,那么我应该可以做这样的事情
public class UniqueUsername : ValidationAttribute
{
private readonly UserManager _manager = manager;
public UniqueUsername (UserManager manager)
{
_manager = manager;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
string username = value.ToString();
if(_manager.Exists(username))
{
return new ValidationResult("The username provided belong to a different user.");
}
return ValidationResult.Success;
}
}
但是,_manager.Exists(username) 是一个同步调用。我想避免阻塞主线程,所以我想要一种调用await _manager.ExistsAsync(username) 的方法来避免阻塞主线程。
有没有办法创建一个属性来验证单个属性并将错误“如果有”写入ModelState?
如果使用数据注释无法做到这一点,是否有不同的方法来验证属性,同时将错误写入ModelState,因此当调用ModelState.IsValid() 或TryValidateModel(model) 时,会调用属性?
【问题讨论】:
-
一般来说,我会避免在
ValidationAttribute内进行数据库调用,因为它们不太适合依赖注入,并且通常被认为是轻量级和快速的。请记住,您始终可以通过ModelState.AddModelError()将您自己的自定义错误添加到ModelState——或者作为自定义IModelBinder的一部分,或者简单地作为从控制器操作中调用的一些逻辑。如果出现任何错误,ModelState.IsValid()将返回false,您将能够像往常一样处理验证错误。
标签: asp.net asp.net-core data-annotations asp.net-core-3.0 asp.net-core-3.1