我正在尝试使用流畅的验证库中的动态消息构建自定义验证。
例如:
public class CreateProcessValidator : AbstractValidator<CreateProcessVM>
{
public CreateProcessValidator()
{
RuleFor(x => x.ProcessFile).Must((x,e) => IsProcessFileValid(x.ProcessFile))).WithMessage("Parse failed with error : {0}");
}
public bool IsProcessFileValid(HttpPostedFileBase file)
{
var errorMessage = "..." // pass result to validaton message ?
// logic
return false;
}
}
这里有解决方法如何传递验证结果吗?
由于
答案 0 :(得分:17)
你尝试过这样的事吗?
public class IsProcessFileValid : PropertyValidator
{
public IsProcessFileValid(): base("{ValidationMessage}") {}
protected override IsValid(PropertyValidatorContext context)
{
if (!IsProcessFileValid1(context))
context.MessageFormatter.AppendArgument("ValidationMessage",
"Custom validation message #1");
if (!IsProcessFileValid2(context))
context.MessageFormatter.AppendArgument("ValidationMessage",
"Custom validation message #2");
// ...etc
return true;
}
private bool IsProcessFileValid1(PropertyValidatorContext context)
{
// logic
return false;
}
private bool IsProcessFileValid2(PropertyValidatorContext context)
{
// logic
return false;
}
// ...etc
}
使用扩展方法:
public static class IsProcessFileValidExtensions
{
public static IRuleBuilderOptions<T, object> MustBeValidProcessFile<T>
(this IRuleBuilder<T, object> ruleBuilder)
{
return ruleBuilder.SetValidator(new IsProcessFileValid());
}
}
...然后在没有自定义WithMessage
的情况下使用它:
public CreateProcessValidator()
{
RuleFor(x => x.ProcessFile).MustBeValidProcessFile();
}
通过创建自定义PropertyValidator
,您可以在该类中封装默认验证消息并使其动态化。但是,在声明.WithMessage
时,您不得使用RuleFor
扩展名,因为这会覆盖您在PropertyValidator
内直接自定义的默认验证邮件。
答案 1 :(得分:2)
没有办法做到这一点。我会将您当前使用的复杂验证方法拆分为较小的方法(IsProcessFileValid1,IsProcessFileValid2,IsProcessFileValid3,...),以便您可以对错误消息进行更细粒度的控制。此外,每种方法都只负责验证一次使它们更可重复使用(单一责任):
RuleFor(x => x.ProcessFile)
.Must(IsProcessFileValid1)
.WithMessage("Message 1")
.Must(IsProcessFileValid2)
.WithMessage("Message 2")
.Must(IsProcessFileValid3)
.WithMessage("Message 3");
另请注意我如何简化lambda,因为该方法可以直接作为参数传递给Must
。
答案 2 :(得分:0)
这是我解决的方法。经过FluentValidation v8.5.0测试
class EmptyValidationMessage : IStringSource
{
public string ResourceName => null;
public Type ResourceType => null;
public string GetString(IValidationContext context)
{
return string.Empty;
}
public static readonly EmptyValidationMessage Instance = new EmptyValidationMessage();
}
public class MyPropValidator : PropertyValidator
{
public MyPropValidator() : base(EmptyValidationMessage.Instance)
{
}
protected override bool IsValid(PropertyValidatorContext context)
{
// if not valid
Options.ErrorMessageSource = new StaticStringSource("my message");
// you can do LanguageStringSource, LazyStringSource, LocalizedStringSource, etc
// example with localized string (https://github.com/clearwaterstream/LocalizedString.FluentValidation)
Options.ErrorMessageSource = new LocalizedStringSource("my message").InFrench("moi message");
return false;
}
}
答案 3 :(得分:0)
在尝试将异常消息插入WithMessage()
时遇到了相同的问题。
它使用以Func<T, string> messageProvider
作为参数的方法重载来工作。
以下是张贴者示例中提供的解决方案(工作代码,FluentValidation v 9.1):
public class CreateProcessVM
{
public object ProcessFile { get; set; }
}
public class CreateProcessValidator : AbstractValidator<CreateProcessVM>
{
public CreateProcessValidator()
{
var message = "Something went wrong.";
RuleFor(x => x.ProcessFile)
.Must((x, e) => IsProcessFileValid(x.ProcessFile, out message))
// .WithMessage(message); will NOT work
.WithMessage(x => message); //Func<CreateProcessVM, string> as parameter
}
public bool IsProcessFileValid(object file, out string errorMessage)
{
errorMessage = string.Empty;
try
{
Validate(file);
return true;
}
catch (InvalidOperationException e)
{
errorMessage = e.Message;
return false;
}
}
private void Validate(object file)
{
throw new InvalidOperationException("File of type .custom is not allowed.");
}
}
还有一个测试,证明我们确实在错误消息中得到了异常消息:
[Fact]
public void Test()
{
var validator = new CreateProcessValidator();
var result = validator.Validate(new CreateProcessVM());
Assert.False(result.IsValid);
Assert.Equal("File of type .custom is not allowed.", result.Errors[0].ErrorMessage);
}