FluentValidation 自定义验证规则链问题
FluentValidation Custom Validation Rule chain issue
我正在尝试使用自定义验证器来验证智能枚举 (Ardalis.SmartEnum)
这里是枚举的 class:
public abstract class FeelingSystemType : SmartEnum<FeelingSystemType>
{
public static FeelingSystemType Positive = new PositiveType();
public static FeelingSystemType Negative = new NegativeType();
private FeelingSystemType(string name, int value) : base(name, value) { }
private class PositiveType : FeelingSystemType
{
internal PositiveType() : base(nameof(Positive), 1) { }
}
private class NegativeType : FeelingSystemType
{
internal NegativeType() : base(nameof(Negative), 2) { }
}
}
这是命令:
public class Command : IRequest<CommandResponsem>
{
public Command() { }
[JsonConverter(typeof(SmartEnumNameConverter<FeelingSystemType, int>))]
public FeelingSystemType Feeling { get; set; }
}
这是命令验证器:
public class CommandValidator : AbstractValidator<Command>
{
public CommandValidator()
{
RuleFor(r => r.Feeling).ValidateFeeling();
}
}
这是自定义验证规则:
public static IRuleBuilder<T, FeelingSystemType> ValidateFeeling<T>(this IRuleBuilder<T, FeelingSystemType> rule)
{
return rule
.NotEmpty()
.WithMessage("A Feeling must be entered")
.Must(feeling => typeof(FeelingSystemType).IsAssignableFrom(feeling?.GetType()))
.WithMessage("Please enter a valid Feeling");
}
当我发送请求时,验证器似乎忽略了 NotEmpty 先于规则的 Must 部分,并且即使在 Feeling 为 null 时仍然继续验证 Must,但正在返回两条消息。我已经尝试在命令验证器中进行验证,但我得到了相同的结果,除非我将 NotEmpty 和 Must 作为两个单独的规则来执行。我非常有信心 Fluent 允许链接,所以我不确定这里出了什么问题?
默认 FV 行为是 运行 通过 属性 的所有规则。如果你想在第一次失败时停止,你需要做一些像设置 cascade mode.
可以在几个地方完成,具体取决于您希望如何应用行为:
- 在您应用的早期某处使用静态选项 (
ValidatorOptions.Global.CascadeMode = CascadeMode.Stop;
)
- 在验证器中使用
CascadeMode = CascadeMode.Stop;
- 关于使用
RuleFor(r => r.Feeling).Cascade(CascadeMode.Stop).ValidateFeeling();
的规则
您的扩展捆绑了 2 条规则,您 可以 在那里指定级联,但您需要使用 IRuleBuilderInitial
界面。我怀疑这意味着您不能将该规则与 属性 验证器中的其他规则链接起来,除非它是第一条规则。无论如何可能是最好的,因为它会混淆来自验证器的级联模式,它有一定的气味。
我正在尝试使用自定义验证器来验证智能枚举 (Ardalis.SmartEnum)
这里是枚举的 class:
public abstract class FeelingSystemType : SmartEnum<FeelingSystemType>
{
public static FeelingSystemType Positive = new PositiveType();
public static FeelingSystemType Negative = new NegativeType();
private FeelingSystemType(string name, int value) : base(name, value) { }
private class PositiveType : FeelingSystemType
{
internal PositiveType() : base(nameof(Positive), 1) { }
}
private class NegativeType : FeelingSystemType
{
internal NegativeType() : base(nameof(Negative), 2) { }
}
}
这是命令:
public class Command : IRequest<CommandResponsem>
{
public Command() { }
[JsonConverter(typeof(SmartEnumNameConverter<FeelingSystemType, int>))]
public FeelingSystemType Feeling { get; set; }
}
这是命令验证器:
public class CommandValidator : AbstractValidator<Command>
{
public CommandValidator()
{
RuleFor(r => r.Feeling).ValidateFeeling();
}
}
这是自定义验证规则:
public static IRuleBuilder<T, FeelingSystemType> ValidateFeeling<T>(this IRuleBuilder<T, FeelingSystemType> rule)
{
return rule
.NotEmpty()
.WithMessage("A Feeling must be entered")
.Must(feeling => typeof(FeelingSystemType).IsAssignableFrom(feeling?.GetType()))
.WithMessage("Please enter a valid Feeling");
}
当我发送请求时,验证器似乎忽略了 NotEmpty 先于规则的 Must 部分,并且即使在 Feeling 为 null 时仍然继续验证 Must,但正在返回两条消息。我已经尝试在命令验证器中进行验证,但我得到了相同的结果,除非我将 NotEmpty 和 Must 作为两个单独的规则来执行。我非常有信心 Fluent 允许链接,所以我不确定这里出了什么问题?
默认 FV 行为是 运行 通过 属性 的所有规则。如果你想在第一次失败时停止,你需要做一些像设置 cascade mode.
可以在几个地方完成,具体取决于您希望如何应用行为:
- 在您应用的早期某处使用静态选项 (
ValidatorOptions.Global.CascadeMode = CascadeMode.Stop;
) - 在验证器中使用
CascadeMode = CascadeMode.Stop;
- 关于使用
RuleFor(r => r.Feeling).Cascade(CascadeMode.Stop).ValidateFeeling();
的规则
您的扩展捆绑了 2 条规则,您 可以 在那里指定级联,但您需要使用 IRuleBuilderInitial
界面。我怀疑这意味着您不能将该规则与 属性 验证器中的其他规则链接起来,除非它是第一条规则。无论如何可能是最好的,因为它会混淆来自验证器的级联模式,它有一定的气味。