Fluent Validation是一个ASP.NET MVC集成验证框架,允许开发人员使用表达式设置验证规则。它是可测试的并且与控制(依赖注入)模式和TDD(测试驱动开发)技术的反转完全兼容。
为什么 ASP.NET Core 说我的表单字段是必需的,即使它没有定义为必需?
我正在使用 .NET 6 和 Fluent Validation,并且我有一个包含以下字段的表单: 我正在使用 .NET 6 和 Fluent Validation,并且我有一个包含以下字段的表单: <form method="post" asp-controller="Product" asp-action="Create" asp-antiforgery="true" autocomplete="off"> <label asp-for="Description">Description</label> <input asp-for="Description" type="text"> <span asp-validation-for="Description" class="error"></span> ... <button class="submit" name="button">Create</button> </form> ProductModel 是: public class ProductModel { public String Description { get; set; } // ... } ProductModel Fluent 验证器是: public class ModelValidator : AbstractValidator<ProductModel> { public ModelValidator() { RuleFor(x => x.Description) .Length(0, 200).WithMessage("Do not exceed 200 characters"); // ... } } 当我提交表单时,如果我将其留空,我会收到描述错误: 描述字段为必填项。 但我的验证器不需要描述。 这发生在所有领域。当未填写时,我会收到类似的错误。 我缺少什么,如何才能使它不需要? 这似乎是由于与模型验证更改相关的问题造成的;特别是在 .NET 6 中。我找到了一个文档链接,它可以比我更好地解释它,但我也会提供代码实现:Microsoft docs builder.Services.AddControllers( options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true); //Removes the required attribute for non-nullable reference types. 我直接从 MS 文档中获取了此代码,因此如果它不能解决您的问题,则可能还有其他原因。 以下是 Microsoft .NET 文档中关于此问题的非常详细的解释: 获取或设置一个值,该值确定是否禁止对不可为空引用类型的属性和参数进行RequiredAttribute的推断。如果 false(默认值),则所有不可空引用类型的行为都将如同已应用 [Required] 一样。如果true,这种行为就会被抑制;出于验证目的,可空引用类型和不可空引用类型的行为相同。 解决这个问题有两种方法,一种是全局的,一种是部分的。 您可以设置: builder.Services.AddControllersWithViews(options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true) 在您的 Program.cs (.NET 6) 中。使用此方法后,所有属性都可以为空。 另一种方法是在你的模型中,你可以像这样设置属性: public class ProductModel { public String? Description { get; set; } // ... } ? 表示该属性可以为空。在此方法中,您可以指定哪些属性可以为空。 当我尝试以 The {fieldName} field is required 的形式使用我的 asp.net API 时,收到了大量验证错误 发现这是由于 C# 8 中的 Nullable Reference Types 造成的 我通过 .csproj 文件选择退出此行为 <PropertyGroup> <TargetFramework>net6.0</TargetFramework> <Nullable>disable</Nullable> </PropertyGroup>
我正在使用 .NET 6 和 Fluent Validation,并且我有一个包含以下字段的表单: 我正在使用 .NET 6 和 Fluent Validation,并且我有一个包含以下字段的表单: <form method="post" asp-controller="Product" asp-action="Create" asp-antiforgery="true" autocomplete="off"> <label asp-for="Description">Description</label> <input asp-for="Description" type="text"> <span asp-validation-for="Description" class="error"></span> ... <button class="submit" name="button">Create</button> </form> ProductModel 是: public class ProductModel { public String Description { get; set; } // ... } ProductModel Fluent 验证器是: public class ModelValidator : AbstractValidator<ProductModel> { public ModelValidator() { RuleFor(x => x.Description) .Length(0, 200).WithMessage("Do not exceed 200 characters"); // ... } } 当我提交表单时,如果我将其留空,我会收到描述错误: 描述字段为必填项。 但我的验证器不需要描述。 这发生在所有领域。当未填写时,我会收到类似的错误。 我错过了什么? 做了一些挖掘,这似乎是由于与模型验证更改相关的问题造成的;特别是在 .NET 6 中。我找到了一个文档链接,它可以比我更好地解释它,但我也会提供代码实现:Microsoft docs builder.Services.AddControllers( options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true); //Removes the required attribute for non-nullable reference types. 我直接从 MS 文档中获取了此代码,因此如果它不能解决您的问题,则可能还有其他原因。 MC文档中对此问题有非常详细的解释: 获取或设置一个值,该值确定是否推断 不可为空的属性和参数的RequiredAttribute 引用类型被抑制。如果为 false(默认值),则所有 不可为 null 的引用类型的行为就像 [Required] 已 应用。如果为真,这种行为将被抑制;可为空的引用 类型和不可为 null 的引用类型的行为相同 验证的目的。 解决这个问题有两种方法,一种是全局的,一种是部分的。 您可以设置: builder.Services.AddControllersWithViews(options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true) 在你的Program.cs(.Net6)中,使用此方法后,所有属性都可以为空。 另一种方法是在你的模型中,你可以像这样设置属性: public class ProductModel { public String? Description { get; set; } // ... } ?表示该属性可以为空,在该方法中,您可以指定哪些属性可以为空。 当我尝试以 The {fieldName} field is required 的形式使用我的 asp.net API 时,收到了大量验证错误 发现这是由于 C# 8 中的 Nullable Reference Types 造成的 我通过 .csproj 文件选择退出此行为 <PropertyGroup> <TargetFramework>net6.0</TargetFramework> <Nullable>disable</Nullable> </PropertyGroup>
FluentValidation:如何从另一个程序集自动注册所有验证器?
我正在为 .Net Core 项目使用“FluentValidation.AspNetCore”库(版本=“8.6.2”)。 我想做的是在 Startup.cs c 中自动注册所有验证器...
FluentValidation 向 WithMessage 传递参数
我在验证器中有以下代码: RuleFor(mb => mb.Amount). 必须((mb, 金额) => { var betLimit = _battlesService.GetBetLimit(mb.BattleId); ...
C# 单元测试 FluentValidation 和模拟嵌套验证器 (.SetValidator)
我正在开发一个 .NET 4.8 项目并使用 FluentValidation v9.5.4。由于我无法控制的原因,我无法更新版本。 使用 FluentValidation 文档中的示例类: 公开课客户...
这是针对 .NET 8 Blazor Web 应用程序的。 我有一个具有编辑器模板的网格,如下所示: @{ CurrentEditedItemSupplier =(上下文为 ItemSupplier)!; 这是针对 .NET 8 Blazor Web 应用程序的。 我有一个带有编辑器模板的网格,如下所示: <EditorTemplate> @{ CurrentlyEditedItemSupplier = (context as ItemSupplier)!; <HiSS.Body.Components.Custom.ItemSelector Items="@Items" CurrentItemSupplier="@CurrentlyEditedItemSupplier" Categories="@Categories" /> <TelerikValidationTooltip For="@(() => CurrentlyEditedItemSupplier.ItemId)" TargetSelector="#Item-field" Position="@TooltipPosition.Bottom"> </TelerikValidationTooltip> } 它包含一个具有 3 个组合框的自定义控件 (ItemSelector)。第一个是类别选择器,用于将项目记录过滤到较小的子集,另外两个链接到项目并显示其中的不同字段,允许用户从 ID 号或描述中进行选择。父网格绑定到 ItemSupplier 类型的对象。它不包含绑定到第一个组合框中的类别 ID。另外两个绑定到对象中的项目 ID。 <TelerikComboBox Id="Category-field" Data="@Categories" @bind-Value="@CurrentCategoryId" TextField="@nameof(Category.Name)" ValueField="@nameof(Category.Id)" OnChange="@FilterItems" Width="39%"> <ComboBoxSettings> <ComboBoxPopupSettings Class="dropdownsize;" /> </ComboBoxSettings> </TelerikComboBox> <TelerikComboBox id="Item-Desc" Data="@FilteredItems" @bind-Value="@CurrentItemSupplier!.ItemId" TextField="@nameof(Item.Description)" ValueField="@nameof(Item.Id)" Width="39%"> <ComboBoxSettings> <ComboBoxPopupSettings Class="dropdownsize;" /> </ComboBoxSettings> </TelerikComboBox> <TelerikValidationTooltip For="@(() => CurrentItemSupplier.ItemId)" TargetSelector="#Item-Desc" Position="@TooltipPosition.Bottom"> </TelerikValidationTooltip> <TelerikComboBox id="Item-ItemNo" Data="@FilteredItems" @bind-Value="@CurrentItemSupplier!.ItemId" TextField="@nameof(Item.ItemNo)" ValueField="@nameof(Item.Id)" Width="20%"> <ComboBoxSettings> <ComboBoxPopupSettings Class="dropdownsize;" /> </ComboBoxSettings> </TelerikComboBox> <TelerikValidationTooltip For="@(() => CurrentItemSupplier.ItemId)" TargetSelector="#Item-ItemNo" Position="@TooltipPosition.Bottom"> </TelerikValidationTooltip> 类别纯粹用于过滤项目以向用户提供较小的列表。不幸的是,验证不喜欢它存在,因为它不存在于验证模型中。如果我注释掉类别组合框,一切正常,但项目列表太大。如何进行验证以忽略自定义控件中的类别组合框? 结果非常简单 - 我所要做的就是将有问题的控件包装在它自己的编辑表单中: <EditForm Model="@dummymodel"> <TelerikComboBox Id="Category-field" Data="@Categories" @bind-Value="@CurrentCategoryId" TextField="@nameof(Category.Name)" ValueField="@nameof(Category.Id)" OnChange="@FilterItems" > <ComboBoxSettings> <ComboBoxPopupSettings Class="dropdownsize;" /> </ComboBoxSettings> </TelerikComboBox> </EditForm> 虚拟模型定义为: private object dummymodel = new object(); 而且效果很好...
“IValidationContext”不包含“CloneForChildValidator”的定义
我将流畅的验证包从 8.6.3 升级到 9.2.2 后收到此错误 有人可以帮忙吗? ` { 公共类PolymorphicValidator:NoopPropertyValidator 其中 TBaseClass : c...
使用 FluentValidation 验证 IEnumerable 模型时出现“无法应用索引器,因为属性链为空”错误?
我正在尝试使用 FluentValidation 验证 IEnumerable 模型,但我不断收到以下错误: System.InvalidOperationException:无法应用索引器,因为属性链为
如何使用 FluentValidation 实现基于角色的验证
我们有许多 Web api 服务当前使用 FluentValidation 和 SharpGrip.FluentValidation.AutoValidation 进行自动异步验证。 效果非常好。 目前
FluentEditForm 说没有数据,尽管输入的数据在那里
下面我的代码是一个流畅的编辑表单。我提交后,它说即使我填写了这些字段仍然需要填写。我的代码有什么问题吗? @page“/movieform” @
使用 FluentValidation 如何在控制器中使用validationContext进行测试
我设置了一个验证器,需要使用正在验证的视图模型之外的值。为此,我使用 ValidationContext 并分配 RootContextData,然后调用 validate 方法...
我想将数据传递给流畅的验证。我认为这很简单,你可以在构造函数中完成。但我不想创建验证器的实例,而是注入它,这使得它变得很困难。 我有 :
对具有正文请求的 GET 请求使用 Fluent Validation 是一种不好的做法吗?
我正在尝试在我的项目中使用 Fluent Validator。到目前为止,我的大多数教程都是使用 post 请求,其中您有一个 json 正文作为对象,并且该对象将被验证...
我一直在尝试创建一个 FluentValidation 规则,在验证其属性之前检查它正在验证的对象的实例是否不为空。 我宁愿封装...
使用 FluentValidation 进行更深入的数据库验证是不好的做法吗?
例如,您可以验证电话号码或电子邮件,这些都在 FV 文档中,但是如果您需要确保该电话号码尚未被经理“X”的员工使用怎么办?我...
使用 FluentValidation 验证集合,返回属性的规则失败错误
我刚刚开始使用 FluentValidation v9.x,想知道如何验证集合中的规则。 基本上如果我有一系列物质 公共类物质 { 公共整数?
如何使用 MediatR 和 FluentValidation 实现通用 ValidationBehavion,以便 ValidationBehavion 仅在命令上触发
我正在使用 CQRS 并为了分隔命令和查询而创建了自定义接口,因此我希望我的 ValidationBehavion 仅在继承 IRequest 的自定义 ICommand 上触发 我正在使用 CQRS 并分离命令和查询,我创建了自定义接口,因此我希望我的 ValidationBehavion 仅在继承 IRequest 的自定义 ICommand 上触发,而不是在所有 IRequest 请求上触发。 为了分离命令和查询,我创建了自定义界面: (作为响应值,我使用 ErrorOr 库。但我认为不值得研究它,只需记住命令和查询总是有响应) public interface ICommand<TResponse> : IRequest<ErrorOr<TResponse>> { } public interface IQuery<TResponse> : IRequest<ErrorOr<TResponse>> { } public interface ICommandHandler<TCommand, TResponse> : IRequestHandler<TCommand, ErrorOr<TResponse>> where TCommand : ICommand<TResponse> { } public interface IQueryHandler<TQuery, TResponse> : IRequestHandler<TQuery, ErrorOr<TResponse>> where TQuery : IQuery<TResponse> { } 我知道一种标准方法,其中 IPipelineBehavior 会向任何请求者触发,然后我们检查该请求者是否有验证器: public class ValidationBehavion<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse> where TResponse : IErrorOr { private readonly IValidator<TRequest>? _validator; public ValidationBehavion(IValidator<TRequest>? validator = null) { _validator = validator; } public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken) { if(_validator is null) { return await next(); } var validationResult = await _validator.ValidateAsync(request); if (validationResult.IsValid) { return await next(); } var validationErrors = validationResult.Errors .ConvertAll(error => Errors.Wands.NotValid( error.PropertyName, error.ErrorMessage)); return (dynamic)validationErrors; } } 由于命令和查询是分离的,我想我可以指定 ICommand 而不是 IRequest 并重做 ValidationBehavion,如下所示: public class ValidationBehavion<TRequest, TResponse> : IPipelineBehavior<TRequest, ErrorOr<TResponse>> where TRequest : ICommand<TResponse> { private readonly IValidator<TRequest> _validator; public ValidationBehavion(IValidator<TRequest> validator) { _validator = validator; } public async Task<ErrorOr<TResponse>> Handle(TRequest request, RequestHandlerDelegate<ErrorOr<TResponse>> next, CancellationToken cancellationToken) { var validationResult = await _validator.ValidateAsync(request); if (validationResult.IsValid) { return await next(); } var validationErrors = validationResult.Errors .ConvertAll(error => Errors.Wands.NotValid( error.PropertyName, error.ErrorMessage)); return validationErrors; } } 但是这个 IPipelineBehavior 根本不起作用,我不知道为什么。 您可能需要注册该行为。你的startup.cs应该看起来像这样: public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddMediatR(typeof(Startup)); services.AddValidatorsFromAssemblyContaining<Startup>(); // Register pipeline behaviors services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>)); services.AddTransient(typeof(IPipelineBehavior<,>), typeof(AuthorizationBehavior<,>)); services.AddTransient(typeof(IPipelineBehavior<,>), typeof(PerformanceBehavior<,>)); services.AddTransient(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehavior<,>)); // Register request pre-processors and post-processors services.AddTransient(typeof(IRequestPreProcessor<>), typeof(ValidationPreProcessor<>)); services.AddTransient(typeof(IRequestPostProcessor<,>), typeof(LoggingPostProcessor<,>)); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } 您在这里有完整的教程:https://argosco.io/using-ipipelinebehavior-irequestpreprocessor-and-irequestpostprocessor-in-a-net-core-api/net/
IPipelineBehavior ValidationBehavior 在 MediatR 中注册时不会被触发
我将使用 LangExt 库的 Result 替换所有异常。问题是 ValidationBehavior 甚至没有被触发。它曾经在方法签名曾经是公开的时候触发...
我如何添加在多个程序集中进行验证的流畅验证。 我在共享类库中也有验证器: 公共类 TestModelValidator :AbstractValidator 如何添加在多个程序集中进行验证的流畅验证。 我在共享类库中也有验证器: public class TestModelValidator : AbstractValidator<TestModel> { rules... } public class TestModel2Validator : AbstractValidator<TestModel2> { rules... } ... public class TestMode999Validator : AbstractValidator<TestMode999> { rules... } in my startup.cs: services.AddValidatorsFromAssemblyContaining<Startup>(); services.AddFluentValidationAutoValidation(); services.AddFluentValidationClientsideAdapters(); 安装包FluentValidation.AspNetCore 然后你可以使用这样的扩展方法: services.AddFluentValidation(fv => { fv.RegisterValidatorsFromAssembly(Assembly.GetExecutingAssembly()); fv.RegisterValidatorsFromAssemblyContaining<Assembly1Class>(); fv.RegisterValidatorsFromAssemblyContaining<Assembly2Class>(); }); 或者您可以使用方法 fv.RegisterValidatorsFromAssemblies() 并传递程序集列表。
我正在尝试为这种情况想出正确的语法: 规则A 规则B 以上两者都是独立的 规则 C - 仅当 RuleA 和 RuleB 通过验证时才会运行。 例子: 用户 ID 存在 (...