EF核心Web API:外键验证



假设我有这些类:

public class User
{
public int? Id { get; set; }
...
}
public class Wallet
{
public int? Id { get; set; }
public string Title {get; set;}
public User Owner { get; set; }
...
}
public class WalletCreationDTO 
{
[Required]
public string Title {get; set;}
[Required]
public int OwnerId { get; set; }
}
[HttpPost]
public async Task<ActionResult> CreateWallet(WalletCreationDto walletDTO) {...}

我必须向前端报告任何错误的参数,如下所示:

{  
"errors": {  
"ownerId": "User by Id does not exist",  
"title": "Must not exceed 8 characters"  
}  
}

如何验证OwnerId?

  • 手动查询数据库似乎无效
  • 默认的ASP.NET Core验证似乎没有任何与数据库访问相关的注释

我最终按照建议使用了fluent验证。这不是最有效的方法,但我要权衡漂亮的错误和简单的代码。

public class WalletCreateDTO
{
[Required]
[MaxLength(20)]
public string Title { get; set; }
[Required]
public int OwnerId { get; set; }
[Required]
public string CurrencyCode { get; set; }
}
public class WalletCreateDTOValidator : AbstractValidator<WalletCreateDTO>
{
public WalletCreateDTOValidator(Data.Database database)
{
this.RuleFor(w => w.OwnerId)
.Must(ownerId => database.Users.Any(user => user.Id == ownerId))
.WithMessage("User does not exist");
this.RuleFor(w=> w.CurrencyCode)
.Must(currencyCode => database.Currencies.Any(currency => currency.Code == currencyCode))
.WithMessage("Currency does not exist");
}
}

--- To anyone reading this in the future ---

NuGet包:FluentValidation.AspNetCore

配置:

public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddFluentValidation(config =>
{
config.RegisterValidatorsFromAssembly(typeof(WalletCreateDTO).Assembly);
});
}

注意:这似乎注册了程序集中的所有验证器。例如,我的所有DTO都在Api.DTOs目录/命名空间中,而且似乎可以将它们全部注册,这很方便。

此外,还有招摇集成:MicroElements.Swashbuckle.FluentValidation

您可以在简单模式下使用它。

[HttpPost]
public async Task<ActionResult> CreateWallet(WalletCreationDto walletDTO)
{
bool isValidOwnerId = /*validationLogic => can use service or Repository or etc... */
if (isValidOwnerId == false)
ModelState.AddModelError("OwnerId", "errorMessage");

if (ModelState.IsValid)
{
//CreateWallet Loigc......
}
//we can get all errors from ModelState
List<ModelError> allErrors = ModelState.Values.SelectMany(v => v.Errors).ToList();
/*
return .... 
*/
}

我还建议你阅读以下两个链接。

四可验证对象

fluentvalidation:用于构建强类型验证规则的流行.NET库。

最新更新