尝试将数据注入FluentValidation验证器:
public class MyFormValidator : AbstractValidator<MyForm>
{
private readonly IQueryable<Models.User> _users;
public MyFormValidator(IQueryable<Models.User> users)
{
_users = users;
...
}
}
Run Code Online (Sandbox Code Playgroud)
我的验证工厂:
public class DependencyResolverValidatorFactory : ValidatorFactoryBase
{
private readonly IContainer container;
public DependencyResolverValidatorFactory(IContainer container)
{
this.container = container;
}
public override IValidator CreateInstance(Type validatorType)
{
return container.ResolveOptionalKeyed<IValidator>(validatorType);
}
}
Run Code Online (Sandbox Code Playgroud)
我的Autofac配置器:
public class AutofacConfigurator
{
public static void Configure()
{
var builder = new ContainerBuilder();
...
builder.RegisterType<MyFormValidator>()
.Keyed<IValidator>(typeof(IValidator<MyForm>))
.As<IValidator>()
// 2nd parameter returns IQueryable<User>
.WithParameter("users", new SqlRepository<User>(dataContext))
.InstancePerRequest();
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource()); …Run Code Online (Sandbox Code Playgroud) 我有一个 Post 方法,根据发布的数据我将返回一个结果。我只想在提供字段时才执行验证。如果没有发布任何值,我不想执行验证。这就是我目前所拥有的。显然,如果该值为空,它将崩溃,因为它需要一个值,我该如何解决这个问题?
public bool IsValidAvailability(int AvailabiltyValue)
{
if (AvailabiltyValue > AvailabilityMax || AvailabiltyValue < AvailabilityMin)
return false;
return true;
}
Run Code Online (Sandbox Code Playgroud)
这是我的验证规则。我可以添加任何内容以使下面的验证仅在提供值时才发生吗?
RuleFor(x => (int)x.Availability).Must(validatorServices.IsValidAvailability).WithMessage("Availability must be between " + validatorServices.AvailabilityMin + " and " + validatorServices.AvailabilityMax);
Run Code Online (Sandbox Code Playgroud) Dears我正在尝试使用SetCollectionValidator验证对象列表,并且列表计数可能有0个对象或更多的对象,所以验证返回错误,直到列表没有像这样的项目
public class SCRequest
{
public List<Attachment> Attachments { get; set; }
}
public class Attachment
{
public int AttachmentId { get; set; }
public string Name { get; set; }
public string FileType { get; set; }
public string FilePath { get; set; }
public string FileUrl { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在用于验证ScRequest我做以下事情
public SCRequestValidator()
{
RuleFor(request => request.Attachments)
.SetCollectionValidator(new AttachmentValidator());
}
Run Code Online (Sandbox Code Playgroud)
并且为了验证附件,我执行以下操作
public AttachmentValidator()
{
RuleFor(x => x.FileUrl)
.NotNull()
.WithMessage(ErrorMessage.B0001)
.NotEmpty()
.WithMessage("Not Allowed Empty");
}
Run Code Online (Sandbox Code Playgroud)
我没有 …
我有一条业务规则说PropertyA应该是的倍数PropertyB。
如您所见,验证并不能单独处理一个属性,而是需要验证两个相互关联的属性。如何使用FluentValidations做到这一点?
谢谢!
我有一个自定义的 FleuntValidation 验证规则,用于检查 Guid 是否有效;
public static class GuidValidator
{
private static Regex isGuid = new Regex(@"^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$", RegexOptions.Compiled);
public static bool IsGuid(string candidate)
{
if (candidate != null)
{
if (isGuid.IsMatch(candidate))
{
return true;
}
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
我想用它来检查 Guid 属性是否有效,然后返回自定义错误消息。
RuleFor(x => x.ShiftId).Must(guid => GuidValidator.IsGuid(guid.ToString())).WithMessage("StopShift.ShiftId.GuidNotValid()");
Run Code Online (Sandbox Code Playgroud)
但是,我的规则没有受到影响,因为我猜 Guid 无效,并且一些内置检查在它之前运行。我如何禁用内置检查以便达到我的自定义规则?
您好,我正在尝试进行计算,并且正在使用流畅的验证包来确保遵守我的规则
验证正在触发并进入规则,但仍然无法 100% 工作
SageOrderMixB sageOrder = new SageOrderMixB();
var validator = new MixValidator();
var results = validator.Validate(sageOrder);
public class MixValidator : AbstractValidator<SageOrderMixB>
{
public MixValidator()
{
RuleFor(x => x.WeightInTons).LessThanOrEqualTo(28).ScalePrecision(2, 2).WithMessage("Weight cannot be greater than 28 and must be a precison of 2"); ;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我输入权重为 29,它仍然会绕过并导致我的单元测试失败
在这里,您会看到我在添加到模型之前进行陷印
if (results.IsValid == false)
{
sberror.Clear();
foreach (var item in results.Errors)
{
sberror.Append(item.ErrorMessage);
}
MessageBox.Show("Please correct the following " + sberror.ToString(), "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
sageOrdersList.Add(sageOrder);
Run Code Online (Sandbox Code Playgroud) 在我正在开发的应用程序中,我使用 Mediatr 及其管道来处理数据库交互、一些次要业务逻辑、验证等。
我可以在管道中处理一些诸如访问控制之类的检查,因为我使用此处描述的上下文对象https://jimmybogard.com/sharing-context-in-mediatr-pipelines/从 ASP 进行。具有用户信息和声明的自定义上下文对象的网络身份。
我遇到的一个问题是,由于这个应用程序是多租户的,我需要确保即使存在一个对象,它也属于该租户,而确保这一点的唯一方法是从数据库中获取该对象并检查它。在我看来,验证不应该有副作用,所以我不想依赖它来填充上下文对象。但是,当 Mediatr 处理程序检查对象是否存在等时,这会将大量验证推送到 Mediatr 处理程序中,从而导致大量重复代码。我真的不想多次查询数据库,因为某些查询可能会很昂贵。
在实际请求处理程序中进行更复杂的验证的另一个问题是获取本质上验证错误的内容。目前,如果其中一项检查失败,我会抛出一个ValidationException,然后由中间件捕获并转换为ProblemDetails返回给 API 调用者的 a 。这基本上是流量控制的例外情况,无论如何,验证失败实际上并不是“例外”。
我对如何解决这个问题的想法是:
在管道中的某个位置,当我构建上下文时,包括尝试从数据库中获取所需的对象。如果其中任何一个为空,验证就会失败。这似乎会使测试变得更加困难,并且需要以某种方式装饰请求(或使用反射),以便管道可以知道尝试加载这些对象。
在验证器中进行查询,但使用某种缓存感知存储库,因此当稍后查询同一对象时,它是从缓存而不是数据库提供的。处理程序还将使用此缓存感知存储库(当前处理程序直接与 EF Core DbContext 交互以进行查询)。这就增加了缓存失效的问题,无论如何,我必须在某个时候处理这个问题(相当多的项目很少被修改)。为了进行测试,可以注入一个实际上不缓存任何内容的虚拟缓存对象。
使来自请求的所有响应实现一个接口(或扩展一个抽象类),该接口具有验证信息、一般成功标志等。这可以直接通过 API 返回,也可以使用一些管道将失败转换为ProblemDetails. 这将为每个响应和处理程序添加一些样板,但避免了流量控制的异常以及其他选项中的缓存/反射问题。
假设对于 1 和 2,任何类型的竞争条件都不是问题。对象不会更改所有者,并且很少出于审计/会计目的而实际从数据库中删除内容。
我知道没有真正适合所有此类问题的方法,但我想知道我是否缺少其他选项,或者拥有类似管道的任何人在使用列出的其中之一时遇到的任何长期可维护性问题选项。
我集成了流畅的验证,对于 POST 请求模型验证来说效果很好
但是将验证器附加到 GET 请求的最佳方法是什么?
public async Task<IActionResult> GetV2Async(Constants.Status status, int? cafeId)
Run Code Online (Sandbox Code Playgroud)
我当前的 POST 请求验证器如下所示:
public CafeAddressRequestValidator()
{
RuleFor(x => x.Name).NotEmpty().WithMessage("Name is required");
RuleFor(x => x.AddressLine1).NotEmpty().WithMessage("AddressLine1 is required");
}
Run Code Online (Sandbox Code Playgroud) 尝试使用 MediatR 在 .Net Core 3.1 微服务中注入 Fluent Validation而不使用Structure Map。
在 Nuget 包下面添加:
<PackageReference Include="FluentValidation.AspNetCore" Version="8.6.2" />
<PackageReference Include="MediatR" Version="4.0.1" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="4.0.0" />
Run Code Online (Sandbox Code Playgroud)
启动.cs:
services.AddMvc(options =>
{
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
options.EnableEndpointRouting = false;
}).AddControllersAsServices()
.AddNewtonsoftJson()
.AddViewLocalization(
LanguageViewLocationExpanderFormat.Suffix,
opts => { opts.ResourcesPath = "Resources"; })
.AddDataAnnotationsLocalization()
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
.AddFluentValidation(fv=> fv.RegisterValidatorsFromAssemblyContaining(typeof(Startup)));
Run Code Online (Sandbox Code Playgroud)
注册的 IPipelineBehavior 和验证器:
services.AddMediatR();
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidatorBehaviour<,>));
Run Code Online (Sandbox Code Playgroud)
ValidatorBehaviour.cs:
public class ValidatorBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
private readonly IValidator<TRequest>[] _validators;
public ValidatorBehaviour(IValidator<TRequest>[] validators) => _validators = validators;
public async Task<TResponse> Handle(TRequest …Run Code Online (Sandbox Code Playgroud) 我有一个需要验证的集合的类。集合上的泛型采用一个接口,可以将不同的类型添加到集合中。
创建支持多态性的 FluentValidation 验证器的最简洁路径是什么?
public interface IWizardStep {}
public class WizardOne : IWizardStep
{
public string Model { get; set; }
}
public class WizardTwo : IWizardStep
{
public string FirstName { get; set; }
}
public class Wizard
{
public Wizard()
{
var w1 = new WizardOne();
var w2 = new WizardTwo();
Steps = new List<IWizardStep>
{
w1,
w2
};
}
public IList<IWizardStep> Steps { get; set; }
}
public class WizardValidator : AbstractValidator<Wizard>
{
public WizardValidator()
{
RuleFor(x …Run Code Online (Sandbox Code Playgroud) fluentvalidation ×10
c# ×6
asp.net-core ×4
asp.net ×3
mediatr ×2
validation ×2
.net ×1
autofac ×1