我们如何在asp.net上使用数据验证?日期不能插入大于当前日期.
我可以AbstractValidators使用a 注册FluentValidation FluentValidatorFactory.但是,它感觉不对,因为并非所有IoC容器注册都在bootstrap/composition root期间发生.相反,流利的验证器由一个单独的工厂注册:
所述组合物根:
public class SimpleDependencyInjector : IServiceProvider
{
public readonly Container Container;
public SimpleDependencyInjector()
{
Container = Bootstrap();
}
internal Container Bootstrap()
{
var container = new Container();
container.Register< // ...register all non-fluent-validator types, then
container.Verify();
return container;
}
public object GetService(Type serviceType)
{
return ((IServiceProvider)Container).GetService(serviceType);
}
}
Run Code Online (Sandbox Code Playgroud)
一个抽象的流利验证工厂,仅依赖于IServiceProvider
public abstract class FluentValidatorFactory : ValidatorFactoryBase
{
private IServiceProvider Injector { get; set; }
protected FluentValidatorFactory(IServiceProvider injector) …Run Code Online (Sandbox Code Playgroud) dependency-injection fluentvalidation fluentvalidation-2.0 open-generics simple-injector
我创建了一个自定义验证器,它测试一个值在枚举的有效值范围内:
public class IsInEnumValidator<T> : PropertyValidator {
public IsInEnumValidator() : base("Property {PropertyName} it not a valid enum value.") { }
protected override bool IsValid(PropertyValidatorContext context) {
if (!typeof(T).IsEnum) return false;
return Enum.IsDefined(typeof(T), context.PropertyValue);
}
}
Run Code Online (Sandbox Code Playgroud)
以及链接验证器的扩展方法:
public static IRuleBuilderOptions<T, TProperty> IsInEnum<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder) {
return ruleBuilder.SetValidator(new IsInEnumValidator<TProperty>());
}
Run Code Online (Sandbox Code Playgroud)
我想使用它像这样:
RuleFor(x => x.Day).IsInEnum<DayOfWeek>();
Run Code Online (Sandbox Code Playgroud)
我的问题:
这不能按预期工作,因为我需要speficy ....IsInEnum<T, DayOfWeek>()而不是所需的....IsInEnum<DayOfWeek>();.我该如何实现这一目标?
我想测试这个自定义验证器 - 不是用这个验证器测试我的数据,而是测试验证器本身.该库的文档解释了如何测试数据,而不是如何测试自定义验证器.库中似乎有很多测试代码,有什么我可以重用的吗?我使用NUnit.
我在我的MVC4项目中使用FluentValidation.每件事都很完美,它与我的IoC(StructureMap)相连.
我有两个问题:
我该如何管理验证器的生命周期?可以让他们成为单身人士吗?或者没有区别,我可以根据自己的需要管理生命周期?这里的最佳做法是什么?
FluentValidation非常好.我一直在使用它进行简单的验证(例如:属性不是空的等).我正在考虑使用它做一些Db验证(比如:属性值是唯一的.)我可以使用StructureMap将我的存储库传递给它,并检查Db的值.这是个好主意吗?或者我应该在我的服务层而不是在我的IValidator中实现这个逻辑?
如果您在类似场景中使用它,您的体验是什么?
我使用FluentValidation来验证我的ASP.NET MVC 5.1视图模型(使用默认的不显眼的客户端验证).我通过Ninject注册/创建我的验证器(viewmodels上没有属性):
FluentValidationModelValidatorProvider.Configure(x => x.ValidatorFactory = new NinjectValidatorFactory(_kernel));
AssemblyScanner.FindValidatorsInAssembly(Assembly.GetExecutingAssembly()).ForEach(match => _kernel.Bind(match.InterfaceType).To(match.ValidatorType));
Run Code Online (Sandbox Code Playgroud)
我有一个在整个应用程序中经常使用的局部视图.此部分视图具有自己的视图模型."主"视图模型(整个视图的视图模型)只是从这个"部分"视图模型继承而来.
public class IndexViewModel : PersonalInfoViewModel { ... }
Run Code Online (Sandbox Code Playgroud)
验证器使用相同的模式:
public class IndexValidator : PersonalInfoValidator { ... }
Run Code Online (Sandbox Code Playgroud)
这工作正常,服务器端验证以及"主"视图上的客户端验证工作.但是不会触发部分视图的客户端验证(data-val-*输入字段上没有属性).
我的"主要"观点 Index.cshtml
@model IndexViewModel
@Html.TextBoxFor(x => x.SomeProperty) // client-side validation works fine
@Html.Partial("PersonalInfo") // client-side validation in the partial view does not work (see below)
Run Code Online (Sandbox Code Playgroud)
我的部分观点PersonalInfo.cshtml:
@model PersonalInfoViewModel
@Html.TextBoxFor(x => x.FirstName) // client-side validation does not work
Run Code Online (Sandbox Code Playgroud)
我注意到当我将局部视图的模型更改为"main"viewmodel时它可以工作:
@model IndexViewModel
@Html.TextBoxFor(x => x.FirstName) // client-side …Run Code Online (Sandbox Code Playgroud) 我有这样的规则:
RuleFor(m => m.Title).Length(1, 75);
Run Code Online (Sandbox Code Playgroud)
但是,如果标题是空的,我仍然得到验证,说明标题长度必须在1个到75字符之间,输入0.
如何更改规则以允许空标题,但如果指定了一个,则必须介于1到75个字符之间?谢谢.
我遇到了FluentValidation的问题,我想显示一条消息,而不管给定链中的验证错误.例如,我已经为下面的一个属性定义了一个验证链.我希望链被评估,任何失败都会导致WithMessage()下面调用中定义的消息.但是,它似乎是短路的,只显示遇到的第一个错误的FluentValidation默认错误消息.见下面的代码:
RuleFor(s => s.ProposalDetail.AgeMin).NotNull()
.GreaterThanOrEqualTo(1)
.LessThanOrEqualTo(99)
.WithMessage("Minimum Age entry is required and must range from 1 to 99 years.");
Run Code Online (Sandbox Code Playgroud)
发生的事情是AgeMin属性为null,因此第一次NotNull()检查失败,验证消息显示为"'Proposal Detail.Ige Min'不能为空." Proposal Detail是封装视图模型的名称.我已经尝试将整个验证器的CascadeMode设置为CascadeMode.Continue,但它没有任何效果.
如何为一个属性验证链完成一条消息?
您好,我正在尝试使用.NET Core获得针对我的webApi的自定义验证响应。
在这里我想有一个响应模型
[{
ErrorCode:
ErrorField:
ErrorMsg:
}]
Run Code Online (Sandbox Code Playgroud)
我有一个验证器类,目前我们只检查ModalState.IsValid验证错误,然后将模型状态对象作为BadRequest传递。
但是新要求要求我们为每个验证失败都具有ErrorCodes。
我的示例验证器类
public class TestModelValidator : AbstractValidator<TestModel>{
public TestModelValidator {
RuleFor(x=> x.Name).NotEmpty().WithErrorCode("1001");
RuleFor(x=> x.Age).NotEmpty().WithErrorCode("1002");
}
}
Run Code Online (Sandbox Code Playgroud)
我可以在操作中使用类似的方法以获得验证结果
选项1:
var validator = new TestModelValidator();
var result = validator.Validate(inputObj);
var errorList = result.Error;
Run Code Online (Sandbox Code Playgroud)
并将操作ValidationResult操作到我的自定义响应对象。或
Opt2:
I can use [CustomizeValidator] attribute and maybe an Interceptors.
Run Code Online (Sandbox Code Playgroud)
但是对于Opt2,我不知道如何从拦截器到控制器操作检索ValidationResult。
我只想编写一个通用方法,这样就避免在每个控制器操作方法中调用Opt1进行验证。
要求指出正确的资源。
我正在尝试创建验证,它可以有两个组并在第一次失败时阻止第二次验证(它包含许多规则).
现在我确实在内部和'main validator'中创建了一个私有的"BasicValidation"类,如下所示:
RuleFor(m => m).SetValidator(new BasicValidation()).DependentRules(() => {
//Complex validation
RuleFor(m => m.IdOfSthInDb)
.MustAsync(ItemMustExists)
.WithMessage("Item does not exist.");
});
Run Code Online (Sandbox Code Playgroud)
这样做但我想避免为每个模型创建'BasicValidation'.
我有一个MediatR管道行为,如下所示:
public class FailFastRequestBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
private readonly IEnumerable<IValidator> _validators;
public FailFastRequestBehavior(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var failures = _validators
.Select(async v => await v.ValidateAsync(request))
.SelectMany(result => result.Result.Errors)
.Where(f => f != null);
return failures.Any()
? Errors(failures)
: next();
}
...
}
Run Code Online (Sandbox Code Playgroud)
像这样的MediatR命令:
public class MyUseCase
{
public class Command : IRequest<CommandResponse>
{
...
}
public class Validator : AbstractValidator<Command>
{
...
}
public class Handler<T>: …Run Code Online (Sandbox Code Playgroud) fluentvalidation ×10
c# ×7
.net ×4
asp.net ×2
asp.net-core ×2
asp.net-mvc ×2
lambda ×1
mediatr ×1
testing ×1
unit-testing ×1
validation ×1