C# EF核心Web API:外键验证
假设我有这些课程:C# EF核心Web API:外键验证,c#,database,validation,asp.net-core,entity-framework-core,C#,Database,Validation,Asp.net Core,Entity Framework Core,假设我有这些课程: 公共类用户 { 公共int?Id{get;set;} ... } 公务舱钱包 { 公共int?Id{get;set;} 公共字符串标题{get;set;} 公共用户所有者{get;set;} ... } 公共级WalletCreationTo { [必需] 公共字符串标题{get;set;} [必需] public int OwnerId{get;set;} } [HttpPost] 公共异步任务CreateWallet(WalletCreationTo walletDTO)
公共类用户
{
公共int?Id{get;set;}
...
}
公务舱钱包
{
公共int?Id{get;set;}
公共字符串标题{get;set;}
公共用户所有者{get;set;}
...
}
公共级WalletCreationTo
{
[必需]
公共字符串标题{get;set;}
[必需]
public int OwnerId{get;set;}
}
[HttpPost]
公共异步任务CreateWallet(WalletCreationTo walletDTO){…}
我必须向前端报告任何错误参数,如下所示:
{
“错误”:{
“ownerId”:“按Id的用户不存在”,
“标题”:“不得超过8个字符”
}
}
如何验证所有者ID
- 手动查询数据库似乎无效
- 默认的ASP.NET核心验证似乎没有任何与数据库访问相关的注释
[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 ....
*/
}
[HttpPost]
公共异步任务
:用于构建强类型验证规则的流行.NET库。我最终使用了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");
}
}
注意:这似乎注册了程序集中的所有验证器。例如,我的所有DTO都在Api.DTOs目录/名称空间中,并且似乎都注册了,这很方便
此外,还有一个招摇过市的集成:微元素。招摇过市。FluentValidation
我建议您尝试FluentValidation。对于服务器端验证,我发现它非常有用。请注意,这不是广告。在控制器中包含流畅的验证似乎很好,但似乎很混乱,因为我正在使用dabatase Context进行验证。您可以创建一个自定义验证器(实现IValidation)并执行检查,看起来很混乱,尽管我需要对其他服务的引用,这些服务只用于验证一个属性。似乎真的没有办法利用数据库自己的方式来验证输入如果你指的是“数据库自己的方式”,这是=>\u context.Users.Any(e=>e.Id==OwnerId)代码>,可以使用相同的方法(_上下文类型可以是DbContext或IdentityDbContext)
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddFluentValidation(config =>
{
config.RegisterValidatorsFromAssembly(typeof(WalletCreateDTO).Assembly);
});
}