在ASP.NET MVC4应用程序中,我们使用FluentValidation来验证我们的模型.在某些情况下,我们只想在另一个属性具有值时验证属性.我们使用When关键字来完成此任务.一个简单的验证类如下所示:
public class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{
RuleFor(item => item.FirstName).NotEmpty();
RuleFor(item => item.LastName).NotEmpty().When(item => !string.IsNullOrEmpty(item.FirstName))
}
}
Run Code Online (Sandbox Code Playgroud)
我们希望对此进行客户端验证.我试图创建一个自定义FluentValidationPropertyValidator.但我找不到一种方法来获取验证规则的When部分.有人能指出我正确的方向吗?
我正在使用ASP.NET MVC与Entity Framework POCO类和FluentValidation框架.它运行良好,验证正在发生(就像我使用DataAnnotations).我甚至让客户端验证工作.而且我很高兴.
由于这是一个测试应用程序,我写的是为了看看我是否可以让新技术一起工作(并沿途学习它们),我现在准备尝试使用ViewModels而不是仅仅将实际模型传递给视图.我打算在我的服务中使用像AutoMapper这样的东西来做模型到ViewModel的来回映射,但我先问了一个问题.
这将如何影响我的验证?我的验证类(使用FluentValidation编写)是应该针对ViewModel而不是Model编写的?或者它是否需要在两个地方发生?关于DataAnnotations(和FluentValidation)的一项重大交易是,您可以在一个可以"无处不在"工作的地方进行验证.并且它实现了这个承诺(大多数情况下),但是如果我开始使用ViewModels,我不会失去这种能力并且必须回到两个地方进行验证吗?
或者我只是想错了?
在看Shrinkr的源代码时(我们都会查看其他项目的源代码来学习,对吧??? :))我注意到以下的kewl代码..(以下简称)
public virtual Foo Foo
{
get;
set
{
Check.Argument.IsNotNull(value, "value");
// then do something.
}
}
Run Code Online (Sandbox Code Playgroud)
注意他们检查参数的流畅方式?好:)
alt text http://cherrythian.com/images/borat.jpg
所以..检查代码,他们有一些自定义类,这样做...
public static class Check
{
public static class Argument
{
public static void IsNotNull(object parameter,
string parameterName)
{ ... }
public static void IsNotNullOrEmpty(string parameter,
string parameterName)
{ ... }
.... etc ....
}
Run Code Online (Sandbox Code Playgroud)
那里有没有共同的框架?
gem install netFluentCheck?
:)
我的NinjectModule中有以下代码行:
Bind<IValidatorFactory>().To<NinjectValidatorFactory>().InSingletonScope();
Run Code Online (Sandbox Code Playgroud)
这曾经工作正常,但在使用Nuget进行一系列更新后,我收到以下错误:
错误3类型'Ninject.Web.Mvc.FluentValidation.NinjectValidatorFactory'不能在泛型类型或方法'Ninject.Syntax.IBindingToSyntax.To()'中用作类型参数'TImplementation'.没有从'Ninject.Web.Mvc.FluentValidation.NinjectValidatorFactory'到'FluentValidation.IValidatorFactory'的隐式引用转换.D:\ Projects\Current ...\Configuration\MainModule.cs 19 13
错误4"FluentValidation.ValidatorFactoryBase"类型在未引用的程序集中定义.您必须添加对程序集'FluentValidation,Version = 2.0.0.0,Culture = neutral,PublicKeyToken = a82054b837897c66'的引用.D:\ Projects\Current ...\Configuration\MainModule.cs 19 13
确实,我没有引用FluentValidation Version = 2.0.0.0,但我确实引用了FluentValidation Version = 3.4.0.0.
根据元数据......
IValidatorFactory并ValidatorFactoryBase在Assembly FluentValidation.dll中定义.NinjectValidatorFactory 在Assembly Ninject.Web.Mvc.FluentValidation.dll中定义.在我的References文件夹中,我有FluentValidation v3.4.0.0和Ninject.Web.Mvc.FluentValidation v3.0.0.0.
我不明白为什么编译器认为我需要FluentValidation Version = 2.0.0.0.
我做错了什么,或者这是Nuget包的问题?
我有以下课程
public class ValidProjectHeader : AbstractValidator<Projects.ProjectHeader>
{
public ValidProjectHeader()
{
RuleFor(x => x.LobId).Must(ValidateLOBIDExists);
RuleFor(x => x.CreatedByUserId).NotEmpty();
RuleFor(x => x.ProjectManagerId).NotEmpty();
RuleFor(x => x.ProjectName).NotEmpty();
RuleFor(x => x.SalesRepId).NotEmpty();
RuleFor(x => x.DeliveryDate).NotEmpty();
RuleFor(x => x.ProjectStatusId).NotEmpty();
RuleFor(x => x.DeptartmentId).NotEmpty();
RuleFor(x => x.CustomerId).NotEmpty();
RuleSet("Insert", () =>
{
RuleFor(x => x.ProjectLines).Must(ValidateProjectLines).SetCollectionValidator(new ValidProjectLine());
});
RuleSet("Update", () =>
{
RuleFor(x => x.ProjectLines).SetCollectionValidator(new ValidProjectLine());
});
}
Run Code Online (Sandbox Code Playgroud)
我想要做的是用rulset调用验证,但我还想在使用RuleSet调用验证时返回"常用"规则.
我调用验证的代码如下
public abstract class BaseValidator
{
private List<ValidationFailure> _errors;
public bool IsValid { get; protected set; }
public List<ValidationFailure> Errors
{
get { …Run Code Online (Sandbox Code Playgroud) 我正在努力使我的Fluent验证RuleSet工作,目前它没有,我不知道为什么会发生这种情况,一切似乎都没问题.我想以某种方式进入执行验证的代码,但RuleSet lambdas是ExpressionTrees,它不提供甚至糟糕的调试体验.
有没有办法调试RuleSet逻辑以查看RuleSets中发生了什么?
从FluentValidation 文档中我了解到我可以通过设置级联模式来中止验证.
RuleFor(x => x.Surname)
.Cascade(CascadeMode.StopOnFirstFailure)
.NotNull()
.NotEqual("foo");
Run Code Online (Sandbox Code Playgroud)
这样,如果属性Surname为null,则不会执行相等性检查并阻止空指针异常.在文档中进一步说明,这不仅适用于规则,也适用于验证器级别.
public class PersonValidator : AbstractValidator<Person> {
public PersonValidator() {
// First set the cascade mode
CascadeMode = CascadeMode.StopOnFirstFailure;
// Rule definitions follow
RuleFor(...)
RuleFor(...)
}
}
Run Code Online (Sandbox Code Playgroud)
我将CascadeMode设置为不在规则定义内,而是设置为验证器的实例.预期的行为是,如果第一个RuleFor 失败,第二个RuleFor将不会被评估,但事实并非如此.无论以前的验证错误如何,都会评估所有规则.
我使用它错了还是我误解了文档?
刚开始使用这个很棒的 api,我遇到了多个DependentRules. 我有这样的规则
RuleFor(d => d.NotificationType).NotEmpty().WithMessage("Required");
When(d => d.NotificationType.ToUpper() == "EMAIL", () =>
{
RuleFor(d => d.NotificationEmail).EmailAddress().WithMessage("Invalid Email Address");
RuleFor(d => d.NotificationEmail).NotEmpty().WithMessage("Required");
});
When(d => d.NotificationType.ToUpper() == "SMS", () =>
{
RuleFor(d => d.NotificationContactNo).NotEmpty().WithMessage("Required");
});
Run Code Online (Sandbox Code Playgroud)
但是,当失败NotificationType时Empty,它已经提出了Required错误。现在在这种情况下,这些其他规则是依赖规则,它们应该只在NotificationType不为空时执行。为此,我将规则修改为:
RuleFor(d => d.NotificationType).NotEmpty().WithMessage("Required").DependentRules(k =>
k.When(d => d.NotificationType.ToUpper() == "EMAIL", () =>
{
RuleFor(d => d.NotificationEmail).EmailAddress().WithMessage("Invalid Email Address");
RuleFor(d => d.NotificationEmail).NotEmpty().WithMessage("Required");
})
);
RuleFor(d => d.NotificationType).NotEmpty().WithMessage("Required").DependentRules(k =>
When(d => d.NotificationType.ToUpper() == "SMS", () =>
{ …Run Code Online (Sandbox Code Playgroud) 我正在为 .Net Core 项目使用“FluentValidation.AspNetCore”库(版本=“8.6.2”)。
我想做的是使用类似这样的东西(这就是我现在使用的)在 Startup.cs 类中自动注册所有验证器:
services.AddControllers().AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<Startup>());
Run Code Online (Sandbox Code Playgroud)
但问题是我的验证器将被移动到另一个程序集(客户端需要),所以我不能使用 Startup 作为注册的参考。
有没有一种方法可以做到这一点,而不必一一注册验证器?
您如何看待这个想法:有些 DTO 需要涉及数据库交互的验证,因此我们在验证器类中注入 DbContext 或存储库类,并使用它进行验证。
public class UserEditSelfResourceValidator : AbstractValidator<UserEditSelfResource>
{
private IUserRepository _userRepository;
public UserEditSelfResourceValidator(IUserRepository userRepository, ILoggedInUserService loggedInUser)
{
_userRepository = userRepository;
RuleFor(mem => mem.ProfileUrl).MustAsync(async (entity, value, c) => await UniqueProfileUrl(entity, value))
.WithMessage("Profile Url must be unique.");
}
public async Task<bool> UniqueProfileUrl(UserEditSelfResource userEditSelf, string newProfileUrl)
{
var user = await _userRepository.FindByProfileUrlAsync(newProfileUrl);
if(user.Id == _loggedInUser.GetId() || user == null)
{
return true;
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
您认为这种想法是一种好的做法还是有问题?
fluentvalidation ×10
c# ×5
asp.net-mvc ×4
.net-core ×2
validation ×2
.net ×1
debugging ×1
ninject ×1
registration ×1
startup ×1
viewmodel ×1