diff --git a/src/FluentValidation.DependencyInjectionExtensions/DependencyInjectionExtensions.cs b/src/FluentValidation.DependencyInjectionExtensions/DependencyInjectionExtensions.cs deleted file mode 100644 index 202573ae2..000000000 --- a/src/FluentValidation.DependencyInjectionExtensions/DependencyInjectionExtensions.cs +++ /dev/null @@ -1,106 +0,0 @@ -#region License -// Copyright (c) .NET Foundation and contributors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// The latest version of this file can be found at https://github.com/FluentValidation/FluentValidation -#endregion - -using FluentValidation.Internal; - -namespace FluentValidation; - -using System; -using System.Collections.Generic; -using Microsoft.Extensions.DependencyInjection; -using Validators; - -/// -/// Extension methods for working with a Service Provider. -/// -public static class DependencyInjectionExtensions { - - /// - /// Gets the service provider associated with the validation context. - /// - /// - /// - /// - [Obsolete("Storing a service provider within a ValidationContext is no longer supported. If you still require this functionality, you should manually store the service provider within context.RootContextData")] - public static IServiceProvider GetServiceProvider(this IValidationContext context) - => Get(context.RootContextData); - - /// - /// Gets the service provider associated with the validation context. - /// - /// - /// - /// - [Obsolete("Storing a service provider within a ValidationContext is no longer supported. If you still require this functionality, you should manually store the service provider within context.RootContextData")] - public static IServiceProvider GetServiceProvider(this MessageBuilderContext context) - => Get(context.ParentContext.RootContextData); - - private static IServiceProvider Get(IDictionary rootContextData) { - if (rootContextData.TryGetValue("_FV_ServiceProvider", out var sp)) { - if (sp is IServiceProvider serviceProvider) { - return serviceProvider; - } - } - - throw new InvalidOperationException("The service provider has not been configured to work with FluentValidation. Making use of InjectValidator or GetServiceProvider is only supported when using the automatic MVC integration."); - } - - /// - /// Sets the service provider associated with the validation context. - /// - /// - /// - [Obsolete("Storing a service provider within a ValidationContext is no longer supported. If you still require this functionality, you should manually store the service provider within context.RootContextData")] - public static void SetServiceProvider(this IValidationContext context, IServiceProvider serviceProvider) { - context.RootContextData["_FV_ServiceProvider"] = serviceProvider; - } - - /// - /// Uses the Service Provider to inject the default validator for the property type. - /// - /// - /// - /// - /// - /// - [Obsolete("The InjectValidator method is deprecated and will be removed in a future release. Please use Constructor Injection instead. See the following page for further details: https://github.com/FluentValidation/FluentValidation/issues/1960")] - public static IRuleBuilderOptions InjectValidator(this IRuleBuilder ruleBuilder, params string[] ruleSets) { - return ruleBuilder.InjectValidator((s, ctx) => s.GetService().GetValidator(), ruleSets); - } - - /// - /// Uses the Service Provider to inject the default validator for the property type. - /// - /// - /// - /// - /// - /// - /// - [Obsolete("The InjectValidator method is deprecated and will be removed in a future release. Please use Constructor Injection instead. See the following page for further details: https://github.com/FluentValidation/FluentValidation/issues/1960")] - public static IRuleBuilderOptions InjectValidator(this IRuleBuilder ruleBuilder, Func, IValidator> callback, params string[] ruleSets) { - var adaptor = new ChildValidatorAdaptor((context, _) => { - var serviceProvider = context.GetServiceProvider(); - var validator = callback(serviceProvider, context); - return validator; - }, typeof(IValidator)); - - adaptor.RuleSets = ruleSets; - return ruleBuilder.SetAsyncValidator(adaptor); - } -} diff --git a/src/FluentValidation.DependencyInjectionExtensions/FluentValidation.DependencyInjectionExtensions.csproj b/src/FluentValidation.DependencyInjectionExtensions/FluentValidation.DependencyInjectionExtensions.csproj index 433a8cb6f..d66f29417 100644 --- a/src/FluentValidation.DependencyInjectionExtensions/FluentValidation.DependencyInjectionExtensions.csproj +++ b/src/FluentValidation.DependencyInjectionExtensions/FluentValidation.DependencyInjectionExtensions.csproj @@ -18,7 +18,7 @@ - + diff --git a/src/FluentValidation.Tests/CascadeModePropertiesTesterLegacy.cs b/src/FluentValidation.Tests/CascadeModePropertiesTesterLegacy.cs deleted file mode 100644 index d2058601a..000000000 --- a/src/FluentValidation.Tests/CascadeModePropertiesTesterLegacy.cs +++ /dev/null @@ -1,187 +0,0 @@ -#region License -// Copyright (c) .NET Foundation and contributors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// The latest version of this file can be found at https://github.com/FluentValidation/FluentValidation -#endregion -#pragma warning disable 618 -#pragma warning disable 1998 - -namespace FluentValidation.Tests; - -using System; -using Xunit; - -public class CascadeModePropertiesTesterLegacy : IDisposable { - TestValidator _validator; - - public CascadeModePropertiesTesterLegacy() { - SetBothGlobalCascadeModes(CascadeMode.Continue); - _validator = new TestValidator(); - } - - public void Dispose() { - SetBothGlobalCascadeModes(CascadeMode.Continue); - } - - [Fact] - public void Setting_global_default_CascadeMode_Stop_sets_both_rule_and_class_level_global_default_properties() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Stop; - - Assert.Equal(CascadeMode.Stop, ValidatorOptions.Global.DefaultRuleLevelCascadeMode); - Assert.Equal(CascadeMode.Stop, ValidatorOptions.Global.DefaultClassLevelCascadeMode); - } - - [Fact] - public void Setting_global_default_CascadeMode_Continue_sets_both_rule_and_class_level_global_default_properties() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Stop; - ValidatorOptions.Global.CascadeMode = CascadeMode.Continue; - - Assert.Equal(CascadeMode.Continue, ValidatorOptions.Global.DefaultRuleLevelCascadeMode); - Assert.Equal(CascadeMode.Continue, ValidatorOptions.Global.DefaultClassLevelCascadeMode); - } - - [Fact] - public void Setting_global_default_CascadeMode_StopOnFirstFailure_sets_rule_Stop_and_class_Continue() { - ValidatorOptions.Global.CascadeMode = CascadeMode.StopOnFirstFailure; - - Assert.Equal(CascadeMode.Stop, ValidatorOptions.Global.DefaultRuleLevelCascadeMode); - Assert.Equal(CascadeMode.Continue, ValidatorOptions.Global.DefaultClassLevelCascadeMode); - } - - [Fact] - public void Setting_class_CascadeMode_Stop_sets_both_rule_and_class_level_properties() { - _validator.CascadeMode = CascadeMode.Stop; - - Assert.Equal(CascadeMode.Stop, _validator.RuleLevelCascadeMode); - Assert.Equal(CascadeMode.Stop, _validator.ClassLevelCascadeMode); - } - - [Fact] - public void Setting_class_CascadeMode_Continue_sets_both_rule_and_class_level_properties() { - _validator.CascadeMode = CascadeMode.Stop; - _validator.CascadeMode = CascadeMode.Continue; - - Assert.Equal(CascadeMode.Continue, _validator.RuleLevelCascadeMode); - Assert.Equal(CascadeMode.Continue, _validator.ClassLevelCascadeMode); - } - - [Fact] - public void Setting_class_CascadeMode_StopOnFirstFailure_sets_rule_Stop_and_class_Continue() { - _validator.CascadeMode = CascadeMode.StopOnFirstFailure; - - Assert.Equal(CascadeMode.Stop, _validator.RuleLevelCascadeMode); - Assert.Equal(CascadeMode.Continue, _validator.ClassLevelCascadeMode); - } - - [Fact] - public void Setting_global_DefaultRuleLevelCascadeMode_to_StopOnFirstFailure_sets_Stop() { - ValidatorOptions.Global.DefaultRuleLevelCascadeMode = CascadeMode.StopOnFirstFailure; - - Assert.Equal(CascadeMode.Stop, ValidatorOptions.Global.DefaultRuleLevelCascadeMode); - } - - [Fact] - public void Setting_global_DefaultClassLevelCascadeMode_to_StopOnFirstFailure_sets_Stop() { - ValidatorOptions.Global.DefaultClassLevelCascadeMode = CascadeMode.StopOnFirstFailure; - - Assert.Equal(CascadeMode.Stop, ValidatorOptions.Global.DefaultClassLevelCascadeMode); - } - - [Fact] - public void Setting_class_RuleLevelCascadeMode_to_StopOnFirstFailure_sets_Stop() { - _validator.RuleLevelCascadeMode = CascadeMode.StopOnFirstFailure; - - Assert.Equal(CascadeMode.Stop, _validator.RuleLevelCascadeMode); - } - - [Fact] - public void Setting_class_ClassLevelCascadeMode_to_StopOnFirstFailure_sets_Stop() { - _validator.ClassLevelCascadeMode = CascadeMode.StopOnFirstFailure; - - Assert.Equal(CascadeMode.Stop, _validator.ClassLevelCascadeMode); - } - - [Fact] - public void Global_default_CascadeMode_Get_returns_Stop_when_both_Stop() { - SetBothGlobalCascadeModes(CascadeMode.Stop); - - Assert.Equal(CascadeMode.Stop, ValidatorOptions.Global.CascadeMode); - } - - [Fact] - public void Global_default_CascadeMode_Get_returns_Continue_when_both_Continue() { - SetBothGlobalCascadeModes(CascadeMode.Stop); - SetBothGlobalCascadeModes(CascadeMode.Continue); - - Assert.Equal(CascadeMode.Continue, ValidatorOptions.Global.CascadeMode); - } - - [Fact] - public void Global_default_CascadeMode_Get_returns_StopOnFirstFailure_when_class_Continue_and_rule_Stop() { - ValidatorOptions.Global.DefaultClassLevelCascadeMode = CascadeMode.Continue; - ValidatorOptions.Global.DefaultRuleLevelCascadeMode = CascadeMode.Stop; - - Assert.Equal(CascadeMode.StopOnFirstFailure, ValidatorOptions.Global.CascadeMode); - } - - [Fact] - public void Global_default_CascadeMode_Get_throws_exception_when_class_Stop_and_rule_Continue() { - ValidatorOptions.Global.DefaultClassLevelCascadeMode = CascadeMode.Stop; - ValidatorOptions.Global.DefaultRuleLevelCascadeMode = CascadeMode.Continue; - - Assert.ThrowsAny(() => ValidatorOptions.Global.CascadeMode); - } - - [Fact] - public void Class_CascadeMode_Get_returns_Stop_when_both_Stop() { - SetBothValidatorCascadeModes(CascadeMode.Stop); - - Assert.Equal(CascadeMode.Stop, _validator.CascadeMode); - } - - [Fact] - public void Class_CascadeMode_Get_returns_Continue_when_both_Continue() { - SetBothValidatorCascadeModes(CascadeMode.Stop); - SetBothValidatorCascadeModes(CascadeMode.Continue); - - Assert.Equal(CascadeMode.Continue, _validator.CascadeMode); - } - - [Fact] - public void Class_CascadeMode_Get_returns_StopOnFirstFailure_when_class_Continue_and_rule_Stop() { - _validator.ClassLevelCascadeMode = CascadeMode.Continue; - _validator.RuleLevelCascadeMode = CascadeMode.Stop; - - Assert.Equal(CascadeMode.StopOnFirstFailure, _validator.CascadeMode); - } - - [Fact] - public void Class_CascadeMode_Get_throws_exception_when_class_Stop_and_rule_Continue() { - _validator.ClassLevelCascadeMode = CascadeMode.Stop; - _validator.RuleLevelCascadeMode = CascadeMode.Continue; - - Assert.ThrowsAny(() => _validator.CascadeMode); - } - - private void SetBothValidatorCascadeModes(CascadeMode cascadeMode) { - _validator.ClassLevelCascadeMode = cascadeMode; - _validator.RuleLevelCascadeMode = cascadeMode; - } - - private static void SetBothGlobalCascadeModes(CascadeMode cascadeMode) { - ValidatorOptions.Global.DefaultClassLevelCascadeMode = cascadeMode; - ValidatorOptions.Global.DefaultRuleLevelCascadeMode = cascadeMode; - } -} diff --git a/src/FluentValidation.Tests/CascadingFailuresTester.cs b/src/FluentValidation.Tests/CascadingFailuresTester.cs index b907b00d3..9c704681f 100644 --- a/src/FluentValidation.Tests/CascadingFailuresTester.cs +++ b/src/FluentValidation.Tests/CascadingFailuresTester.cs @@ -117,14 +117,6 @@ public class CascadingFailuresTester : IDisposable { results.Errors.Count.ShouldEqual(1); } - [Fact] - public void Validation_stops_on_first_failure_when_globaldefault_both_Continue_and_ruleleveloverride_Stop_legacy() { - SetBothGlobalCascadeModes(CascadeMode.Continue); - _validator.RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().Equal("Foo"); - var results = _validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(1); - } - [Fact] public void Validation_continues_to_second_validator_when_first_validator_succeeds_and_globaldefault_both_Stop() { SetBothGlobalCascadeModes(CascadeMode.Stop); @@ -216,15 +208,6 @@ public class CascadingFailuresTester : IDisposable { results.Errors.Count.ShouldEqual(1); } - [Fact] - public void Validation_stops_on_failure_when_classlevel_Continue_and_ruleleveldefault_Continue_and_ruleleveloverride_Stop_legacy() { - SetBothValidatorCascadeModes(CascadeMode.Continue); - - _validator.RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().Equal("Foo"); - var results = _validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(1); - } - [Fact] public void Cascade_mode_can_be_set_after_validator_instantiated() { _validator.RuleFor(x => x.Surname).NotNull().Equal("Foo"); @@ -321,15 +304,6 @@ public class CascadingFailuresTester : IDisposable { results.Errors.Count.ShouldEqual(1); } - [Fact] - public async Task Validation_stops_on_first_Failure_when_globaldefault_both_Continue_and_ruleleveloverride_Stop_async_legacy() { - SetBothGlobalCascadeModes(CascadeMode.Continue); - _validator.RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await _validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] public async Task Validation_stops_on_first_Failure_when_globaldefault_both_Continue_and_ruleleveloverride_Stop_async_and_async_validator_is_invoked_synchronously() { SetBothGlobalCascadeModes(CascadeMode.Continue); @@ -338,14 +312,6 @@ public class CascadingFailuresTester : IDisposable { results.Errors.Count.ShouldEqual(1); } - [Fact] - public async Task Validation_stops_on_first_Failure_when_globaldefault_both_Continue_and_ruleleveloverride_Stop_async_and_async_validator_is_invoked_synchronously_legacy() { - SetBothGlobalCascadeModes(CascadeMode.Continue); - _validator.RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().Equal("Foo"); - var results = await _validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } - [Fact] public async Task Validation_continues_to_second_validator_when_first_validator_succeeds_and_globaldefault_both_Stop_async() { SetBothGlobalCascadeModes(CascadeMode.Stop); @@ -465,15 +431,6 @@ public class CascadingFailuresTester : IDisposable { results.Errors.Count.ShouldEqual(1); } - [Fact] - public async Task Validation_stops_on_failure_when_classlevel_Continue_and_ruleleveldefault_Continue_and_ruleleveloverride_Stop_async_legacy() { - SetBothValidatorCascadeModes(CascadeMode.Continue); - - _validator.RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await _validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } - [Fact] public async Task Cascade_mode_can_be_set_after_validator_instantiated_async() { _validator.RuleFor(x => x.Surname).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); @@ -490,6 +447,14 @@ public class CascadingFailuresTester : IDisposable { results.Errors.Count.ShouldEqual(1); } + [Fact] + public void CascadeMode_values_should_correspond_to_correct_integers() { + // 12.0 removed the "StopOnFirstFailure" option which was value 1. + // For compatibility, "Stop" should still equate to 2, rather than being renumbered to 1. + Assert.Equal(0, (int)CascadeMode.Continue); + Assert.Equal(2, (int)CascadeMode.Stop); + } + private void SetBothValidatorCascadeModes(CascadeMode cascadeMode) { _validator.ClassLevelCascadeMode = cascadeMode; _validator.RuleLevelCascadeMode = cascadeMode; diff --git a/src/FluentValidation.Tests/CascadingFailuresTesterLegacy.cs b/src/FluentValidation.Tests/CascadingFailuresTesterLegacy.cs deleted file mode 100644 index 241b461c6..000000000 --- a/src/FluentValidation.Tests/CascadingFailuresTesterLegacy.cs +++ /dev/null @@ -1,364 +0,0 @@ -#region License -// Copyright (c) .NET Foundation and contributors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// The latest version of this file can be found at https://github.com/FluentValidation/FluentValidation -#endregion -#pragma warning disable 618 -#pragma warning disable 1998 - -namespace FluentValidation.Tests; - -using System; -using System.Threading.Tasks; -using Xunit; - -public class CascadingFailuresTesterLegacy : IDisposable { - TestValidator validator; - - public CascadingFailuresTesterLegacy() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Continue; - validator = new TestValidator(); - } - - public void Dispose() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Continue; - } - - [Fact] - public void Validation_continues_on_failure() { - validator.RuleFor(x => x.Surname).NotNull().Equal("Foo"); - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(2); - } - - [Fact] - public void Validation_stops_on_first_failure() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Stop; - - validator.RuleFor(x => x.Surname).NotNull().Equal("Foo"); - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public void Validation_stops_on_first_failure_legacy() { - ValidatorOptions.Global.CascadeMode = CascadeMode.StopOnFirstFailure; - - validator.RuleFor(x => x.Surname).NotNull().Equal("Foo"); - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public void Validation_continues_on_failure_when_set_to_Stop_globally_and_overriden_at_rule_level() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Stop; - - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.Continue).NotNull().Equal("Foo"); - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(2); - } - - [Fact] - public void Validation_continues_on_failure_when_set_to_Stop_globally_and_overriden_at_rule_level_legacy() { - ValidatorOptions.Global.CascadeMode = CascadeMode.StopOnFirstFailure; - - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.Continue).NotNull().Equal("Foo"); - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(2); - } - - [Fact] - public void Validation_stops_on_first_Failure_when_set_to_Continue_globally_and_overriden_at_rule_level() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Continue; - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.Stop).NotNull().Equal("Foo"); - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public void Validation_stops_on_first_Failure_when_set_to_Continue_globally_and_overriden_at_rule_level_legacy() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Continue; - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().Equal("Foo"); - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public void Validation_continues_to_second_validator_when_first_validator_succeeds_and_cascade_set_to_stop() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Stop; - validator.RuleFor(x => x.Surname).NotNull().Length(2, 10); - var result = validator.Validate(new Person() {Surname = "x"}); - result.IsValid.ShouldBeFalse(); - } - - [Fact] - public void Validation_continues_to_second_validator_when_first_validator_succeeds_and_cascade_set_to_stop_legacy() { - ValidatorOptions.Global.CascadeMode = CascadeMode.StopOnFirstFailure; - validator.RuleFor(x => x.Surname).NotNull().Length(2, 10); - var result = validator.Validate(new Person() {Surname = "x"}); - result.IsValid.ShouldBeFalse(); - } - - [Fact] - public void Validation_stops_on_first_failure_when_set_to_StopOnFirstFailure_at_validator_level() { - validator.CascadeMode = CascadeMode.Stop; - - validator.RuleFor(x => x.Surname).NotNull().Equal("Foo"); - validator.RuleFor(x => x.Surname).NotNull().Equal("Foo"); - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public void Validation_stops_on_first_failure_when_set_to_StopOnFirstFailure_at_validator_level_legacy() { - validator.CascadeMode = CascadeMode.StopOnFirstFailure; - - validator.RuleFor(x => x.Surname).NotNull().Equal("Foo"); - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public void Validation_continues_when_set_to_Continue_at_validator_level() { - validator.CascadeMode = CascadeMode.Continue; - - validator.RuleFor(x => x.Surname).NotNull().Equal("Foo"); - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(2); - } - - [Fact] - public void Validation_continues_on_failure_when_set_to_Stop_at_validator_level_and_overriden_at_rule_level() { - validator.CascadeMode = CascadeMode.Stop; - - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.Continue).NotNull().Equal("Foo"); - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(2); - } - - [Fact] - public void Validation_continues_on_failure_when_set_to_StopOnFirstFailure_at_validator_level_and_overriden_at_rule_level_legacy() { - validator.CascadeMode = CascadeMode.StopOnFirstFailure; - - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.Continue).NotNull().Equal("Foo"); - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(2); - } - - [Fact] - public void Validation_stops_on_failure_when_set_to_Continue_and_overriden_at_rule_level() { - validator.CascadeMode = CascadeMode.Continue; - - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.Stop).NotNull().Equal("Foo"); - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public void Validation_stops_on_failure_when_set_to_Continue_and_overriden_at_rule_level_legacy() { - validator.CascadeMode = CascadeMode.Continue; - - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().Equal("Foo"); - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public void Cascade_mode_can_be_set_after_validator_instantiated() { - validator.RuleFor(x => x.Surname).NotNull().Equal("Foo"); - validator.CascadeMode = CascadeMode.Stop; - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public void Cascade_mode_can_be_set_after_validator_instantiated_legacy() { - validator.RuleFor(x => x.Surname).NotNull().Equal("Foo"); - validator.CascadeMode = CascadeMode.StopOnFirstFailure; - var results = validator.Validate(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public async Task Validation_continues_on_failure_async() { - validator.RuleFor(x => x.Surname).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(2); - } - - [Fact] - public async Task Validation_stops_on_first_failure_async() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Stop; - - validator.RuleFor(x => x.Surname).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public async Task Validation_stops_on_first_failure_async_legacy() { - ValidatorOptions.Global.CascadeMode = CascadeMode.StopOnFirstFailure; - - validator.RuleFor(x => x.Surname).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public async Task Validation_continues_on_failure_when_set_to_Stop_globally_and_overriden_at_rule_level_async() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Stop; - - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.Continue).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(2); - } - - [Fact] - public async Task Validation_continues_on_failure_when_set_to_Stop_globally_and_overriden_at_rule_level_async_legacy() { - ValidatorOptions.Global.CascadeMode = CascadeMode.StopOnFirstFailure; - - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.Continue).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(2); - } - - [Fact] - public async Task Validation_stops_on_first_Failure_when_set_to_Continue_globally_and_overriden_at_rule_level_async() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Continue; - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.Stop).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public async Task Validation_stops_on_first_Failure_when_set_to_Continue_globally_and_overriden_at_rule_level_async_legacy() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Continue; - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - - [Fact] - public async Task Validation_stops_on_first_Failure_when_set_to_Continue_globally_and_overriden_at_rule_level_and_async_validator_is_invoked_synchronously() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Continue; - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.Stop).NotNull().Equal("Foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public async Task Validation_stops_on_first_Failure_when_set_to_Continue_globally_and_overriden_at_rule_level_and_async_validator_is_invoked_synchronously_legacy() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Continue; - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().Equal("Foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public async Task Validation_continues_to_second_validator_when_first_validator_succeeds_and_cascade_set_to_stop_async() { - ValidatorOptions.Global.CascadeMode = CascadeMode.Stop; - validator.RuleFor(x => x.Surname).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var result = await validator.ValidateAsync(new Person {Surname = "x"}); - result.IsValid.ShouldBeFalse(); - } - - [Fact] - public async Task Validation_continues_to_second_validator_when_first_validator_succeeds_and_cascade_set_to_stop_async_legacy() { - ValidatorOptions.Global.CascadeMode = CascadeMode.StopOnFirstFailure; - validator.RuleFor(x => x.Surname).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var result = await validator.ValidateAsync(new Person {Surname = "x"}); - result.IsValid.ShouldBeFalse(); - } - - [Fact] - public async Task Validation_stops_on_first_failure_when_set_to_StopOnFirstFailure_at_validator_level_async() { - validator.CascadeMode = CascadeMode.Stop; - - validator.RuleFor(x => x.Surname).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - validator.RuleFor(x => x.Surname).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] public async Task Validation_stops_on_first_failure_when_set_to_StopOnFirstFailure_at_validator_level_async_legacy() { - validator.CascadeMode = CascadeMode.StopOnFirstFailure; - - validator.RuleFor(x => x.Surname).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public async Task Validation_continues_when_set_to_Continue_at_validator_level_async() { - validator.CascadeMode = CascadeMode.Continue; - - validator.RuleFor(x => x.Surname).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(2); - } - - [Fact] - public async Task Validation_continues_on_failure_when_set_to_StopOnFirstFailure_at_validator_level_and_overriden_at_rule_level_async() { - validator.CascadeMode = CascadeMode.Stop; - - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.Continue).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(2); - } - - [Fact] - public async Task Validation_continues_on_failure_when_set_to_StopOnFirstFailure_at_validator_level_and_overriden_at_rule_level_async_legacy() { - validator.CascadeMode = CascadeMode.StopOnFirstFailure; - - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.Continue).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(2); - } - - [Fact] - public async Task Validation_stops_on_failure_when_set_to_Continue_and_overriden_at_rule_level_async() { - validator.CascadeMode = CascadeMode.Continue; - - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.Stop).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public async Task Validation_stops_on_failure_when_set_to_Continue_and_overriden_at_rule_level_async_legacy() { - validator.CascadeMode = CascadeMode.Continue; - - validator.RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public async Task Cascade_mode_can_be_set_after_validator_instantiated_async() { - validator.RuleFor(x => x.Surname).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - validator.CascadeMode = CascadeMode.Stop; - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } - - [Fact] - public async Task Cascade_mode_can_be_set_after_validator_instantiated_async_legacy() { - validator.RuleFor(x => x.Surname).MustAsync(async (x, c) => x != null).MustAsync(async (x, c) => x == "foo"); - validator.CascadeMode = CascadeMode.StopOnFirstFailure; - var results = await validator.ValidateAsync(new Person()); - results.Errors.Count.ShouldEqual(1); - } -} diff --git a/src/FluentValidation.Tests/ChainedValidationTester.cs b/src/FluentValidation.Tests/ChainedValidationTester.cs index 3c584af9a..135efcfa6 100644 --- a/src/FluentValidation.Tests/ChainedValidationTester.cs +++ b/src/FluentValidation.Tests/ChainedValidationTester.cs @@ -177,9 +177,7 @@ public class ChainedValidationTester { public class DepartmentValidator : AbstractValidator { public DepartmentValidator() { -#pragma warning disable 618 - CascadeMode = CascadeMode.StopOnFirstFailure; -#pragma warning restore 618 + RuleLevelCascadeMode = CascadeMode.Stop; RuleFor(x => x.Manager).NotNull(); RuleFor(x => x.Assistant.Surname).NotEqual(x => x.Manager.Surname).When(x => x.Assistant != null && x.Manager.Surname != null); } diff --git a/src/FluentValidation.Tests/ForEachRuleTests.cs b/src/FluentValidation.Tests/ForEachRuleTests.cs index 39ccc0478..2b889e698 100644 --- a/src/FluentValidation.Tests/ForEachRuleTests.cs +++ b/src/FluentValidation.Tests/ForEachRuleTests.cs @@ -220,12 +220,10 @@ await ExclusiveDelay(1) [Fact] public void Can_use_cascade_with_RuleForEach() { var validator = new InlineValidator(); -#pragma warning disable 618 validator.RuleForEach(x => x.NickNames) - .Cascade(CascadeMode.StopOnFirstFailure) + .Cascade(CascadeMode.Stop) .NotNull() .NotEqual("foo"); -#pragma warning restore 618 var result = validator.Validate(new Person {NickNames = new string[] {null}}); result.Errors.Count.ShouldEqual(1); diff --git a/src/FluentValidation/AbstractValidator.cs b/src/FluentValidation/AbstractValidator.cs index 5a317776b..4161ff8eb 100644 --- a/src/FluentValidation/AbstractValidator.cs +++ b/src/FluentValidation/AbstractValidator.cs @@ -38,59 +38,6 @@ public abstract class AbstractValidator : IValidator, IEnumerable _classLevelCascadeMode = () => ValidatorOptions.Global.DefaultClassLevelCascadeMode; private Func _ruleLevelCascadeMode = () => ValidatorOptions.Global.DefaultRuleLevelCascadeMode; -#pragma warning disable 618 - /// - /// - /// Gets a single mode value representing the default values of - /// - /// and ., based on the same logic as used when setting - /// this property as described below. - /// - /// - /// Sets the values of - /// and . - /// - /// - /// If set to or , then both properties are set - /// to that value. - /// - /// - /// If set to the deprecated , - /// then - /// is set to , and - /// is set to . - /// This results in the same behaviour as before this property was deprecated. - /// - /// - [Obsolete($"Use {nameof(ClassLevelCascadeMode)} and/or {nameof(RuleLevelCascadeMode)} instead. " + - "CascadeMode will be removed in a future release. " + - "For more details, see https://docs.fluentvalidation.net/en/latest/cascade.html")] - public CascadeMode CascadeMode { - get { - if (ClassLevelCascadeMode == RuleLevelCascadeMode) { - return ClassLevelCascadeMode; - } - else if (ClassLevelCascadeMode == CascadeMode.Continue && RuleLevelCascadeMode == CascadeMode.Stop) { - return CascadeMode.StopOnFirstFailure; - } - else { - throw new Exception( - $"There is no conversion to a single {nameof(CascadeMode)} value from the current combination of " + - $"{nameof(ClassLevelCascadeMode)} and {nameof(RuleLevelCascadeMode)}. " + - $"Please use these properties instead of the deprecated {nameof(CascadeMode)} going forward."); - } - } - set { - ClassLevelCascadeMode = value == CascadeMode.StopOnFirstFailure - ? CascadeMode.Continue - : value; - - RuleLevelCascadeMode = value == CascadeMode.StopOnFirstFailure - ? CascadeMode.Stop - : value; - } - } - /// /// /// Sets the cascade behaviour in between rules in this validator. @@ -106,17 +53,10 @@ public abstract class AbstractValidator : IValidator, IEnumerablewithin individual rules is controlled by /// . /// - /// - /// This cannot be set to the deprecated . - /// . Attempting to do so it will actually - /// result in being used. - /// /// public CascadeMode ClassLevelCascadeMode { get => _classLevelCascadeMode(); - set => _classLevelCascadeMode = value == CascadeMode.StopOnFirstFailure - ? () => CascadeMode.Stop - : () => value; + set => _classLevelCascadeMode = () => value; } /// @@ -134,20 +74,12 @@ public abstract class AbstractValidator : IValidator, IEnumerable /// Note that cascade behaviour between rules is controlled by . /// - /// - /// This cannot be set to the deprecated . - /// . Attempting to do so it will actually - /// result in being used. - /// /// public CascadeMode RuleLevelCascadeMode { get => _ruleLevelCascadeMode(); - set => _ruleLevelCascadeMode = value == CascadeMode.StopOnFirstFailure - ? () => CascadeMode.Stop - : () => value; + set => _ruleLevelCascadeMode = () => value; } -#pragma warning restore 618 ValidationResult IValidator.Validate(IValidationContext context) { context.Guard("Cannot pass null to Validate", nameof(context)); return Validate(ValidationContext.GetFromNonGenericContext(context)); diff --git a/src/FluentValidation/Enums.cs b/src/FluentValidation/Enums.cs index e08ffcd21..766392430 100644 --- a/src/FluentValidation/Enums.cs +++ b/src/FluentValidation/Enums.cs @@ -28,23 +28,13 @@ public enum CascadeMode { /// When a rule/validator fails, execution continues to the next rule/validator. /// For more information, see the methods/properties that accept this enum as a parameter. /// - Continue, - /// - /// For more information, see the methods/properties that accept this enum as a parameter. - /// - [Obsolete( - $"The behaviour of {nameof(StopOnFirstFailure)} has been replaced by use of the " + - $"separate validator-level properties {nameof(AbstractValidator.ClassLevelCascadeMode)} " + - $"and {nameof(AbstractValidator.RuleLevelCascadeMode)}, " + - $"and their global default equivalents. {nameof(StopOnFirstFailure)} will be removed in a later release. " + - "For more details, see https://docs.fluentvalidation.net/en/latest/cascade.html .")] - StopOnFirstFailure, + Continue = 0, /// /// When a rule/validator fails, validation is stopped for the current rule/validator. /// For more information, see the methods/properties that accept this enum as a parameter. /// - Stop, + Stop = 2, // Note Stop is 2 for backwards compatibility. The StopOnFirstFailure option was 1, which was removed in 12.0. This is explicitly set to 2 to prevent it from being automatically renumbered to 1. } /// diff --git a/src/FluentValidation/Internal/RuleBase.cs b/src/FluentValidation/Internal/RuleBase.cs index 386c42256..64a1febba 100644 --- a/src/FluentValidation/Internal/RuleBase.cs +++ b/src/FluentValidation/Internal/RuleBase.cs @@ -113,13 +113,7 @@ internal abstract class RuleBase : IValidationRule public CascadeMode CascadeMode { get => _cascadeModeThunk(); - set { -#pragma warning disable 618 - _cascadeModeThunk = value == CascadeMode.StopOnFirstFailure - ? () => CascadeMode.Stop - : () => value; -#pragma warning restore 618 - } + set => _cascadeModeThunk = () => value; } /// diff --git a/src/FluentValidation/ValidatorOptions.cs b/src/FluentValidation/ValidatorOptions.cs index 57c9da070..9acf8c5d3 100644 --- a/src/FluentValidation/ValidatorOptions.cs +++ b/src/FluentValidation/ValidatorOptions.cs @@ -36,107 +36,21 @@ public class ValidatorConfiguration { private Func _errorCodeResolver = DefaultErrorCodeResolver; private ILanguageManager _languageManager = new LanguageManager(); - private CascadeMode _defaultClassLevelCascadeMode = CascadeMode.Continue; - private CascadeMode _defaultRuleLevelCascadeMode = CascadeMode.Continue; - - /// - /// - /// Gets a single mode value representing the default values of - /// - /// and ., based on the same logic as used when setting - /// this property as described below. - /// - /// - /// Sets the default values of - /// and . - /// - /// - /// If set to or , then both properties are set - /// to that value by default. - /// - /// - /// If set to the deprecated , - /// then - /// is set to by default, and - /// is set to by default. - /// This results in the same behaviour as before this property was deprecated. - /// - /// - /// Note that cascade mode behaviour within individual rules is controlled by - /// . - /// - /// - [Obsolete($"Use {nameof(DefaultClassLevelCascadeMode)} and/or {nameof(DefaultRuleLevelCascadeMode)} instead. " + - "CascadeMode will be removed in a future release. " + - "For more details, see https://docs.fluentvalidation.net/en/latest/cascade.html")] - public CascadeMode CascadeMode { -#pragma warning disable 618 - get { - if (_defaultClassLevelCascadeMode == _defaultRuleLevelCascadeMode) { - return _defaultClassLevelCascadeMode; - } - else if (_defaultClassLevelCascadeMode == CascadeMode.Continue && _defaultRuleLevelCascadeMode == CascadeMode.Stop) { - return CascadeMode.StopOnFirstFailure; - } - else { - throw new Exception( - $"There is no conversion to a single {nameof(CascadeMode)} value from the current combination of " + - $"{nameof(DefaultClassLevelCascadeMode)} and {nameof(DefaultRuleLevelCascadeMode)}. " + - $"Please use these properties instead of the deprecated {nameof(CascadeMode)} going forward."); - } - } - - set { - DefaultClassLevelCascadeMode = value == CascadeMode.StopOnFirstFailure - ? CascadeMode.Continue - : value; - - DefaultRuleLevelCascadeMode = value == CascadeMode.StopOnFirstFailure - ? CascadeMode.Stop - : value; -#pragma warning restore 618 - } - } - /// /// /// Sets the default value for . /// Defaults to if not set. /// - /// - /// This cannot be set to the deprecated . - /// . Attempting to do so it will actually - /// result in being used. - /// /// - public CascadeMode DefaultClassLevelCascadeMode { - get => _defaultClassLevelCascadeMode; -#pragma warning disable 618 - set => _defaultClassLevelCascadeMode = value == CascadeMode.StopOnFirstFailure - ? CascadeMode.Stop - : value; -#pragma warning restore 618 - } + public CascadeMode DefaultClassLevelCascadeMode { get; set; } = CascadeMode.Continue; /// /// /// Sets the default value for /// Defaults to if not set. /// - /// - /// This cannot be set to the deprecated . - /// . Attempting to do so it will actually - /// result in being used. - /// /// - public CascadeMode DefaultRuleLevelCascadeMode { - get => _defaultRuleLevelCascadeMode; -#pragma warning disable 618 - set => _defaultRuleLevelCascadeMode = value == CascadeMode.StopOnFirstFailure - ? CascadeMode.Stop - : value; -#pragma warning restore 618 - } + public CascadeMode DefaultRuleLevelCascadeMode { get; set; } = CascadeMode.Continue; /// /// Default severity level