From 72f0886046d13492bd36a16ed977e794eb18e053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Tich=C3=BD?= Date: Tue, 8 Oct 2024 20:39:30 +0200 Subject: [PATCH 1/2] Initialized service provider in validation context. --- .../ViewModel/Validation/ViewModelValidator.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Framework/Framework/ViewModel/Validation/ViewModelValidator.cs b/src/Framework/Framework/ViewModel/Validation/ViewModelValidator.cs index ad7e0388cd..24d50b2fdf 100644 --- a/src/Framework/Framework/ViewModel/Validation/ViewModelValidator.cs +++ b/src/Framework/Framework/ViewModel/Validation/ViewModelValidator.cs @@ -66,6 +66,8 @@ private IEnumerable ValidateViewModel(object? viewMode // validate all properties on the object var map = viewModelSerializationMapper.GetMap(viewModel.GetType()); + var dotvvmConfiguration = (DotvvmConfiguration)validationItems[typeof(DotvvmConfiguration)]!; + foreach (var property in map.Properties.Where(p => p.TransferToServer)) { var value = property.PropertyInfo.GetValue(viewModel); @@ -74,6 +76,7 @@ private IEnumerable ValidateViewModel(object? viewMode if (property.ValidationRules.Any()) { var context = new ValidationContext(viewModel, validationItems) { MemberName = property.Name }; + context.InitializeServiceProvider(dotvvmConfiguration.ServiceProvider.GetService); foreach (var rule in property.ValidationRules) { @@ -103,8 +106,11 @@ private IEnumerable ValidateViewModel(object? viewMode if (viewModel is IValidatableObject) { - foreach (var error in ((IValidatableObject)viewModel).Validate( - new ValidationContext(viewModel, validationItems))) + var validationContext = new ValidationContext(viewModel, validationItems); + validationContext.InitializeServiceProvider(dotvvmConfiguration.ServiceProvider.GetService); + var errors = ((IValidatableObject)viewModel).Validate(validationContext); + + foreach (var error in errors) { var paths = new List(); if (error.MemberNames != null) @@ -114,6 +120,7 @@ private IEnumerable ValidateViewModel(object? viewMode paths.Add(memberPath); } } + if (!paths.Any()) { paths.Add(string.Empty); From 74dc13f2b808774659b5e5e0525fab80c7b68538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Herceg?= Date: Thu, 10 Oct 2024 14:01:20 +0200 Subject: [PATCH 2/2] Added test for service provider in validation context --- .../ViewModel/ViewModelValidatorTests.cs | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Tests/ViewModel/ViewModelValidatorTests.cs b/src/Tests/ViewModel/ViewModelValidatorTests.cs index b0f1cdb4a8..add6de242c 100644 --- a/src/Tests/ViewModel/ViewModelValidatorTests.cs +++ b/src/Tests/ViewModel/ViewModelValidatorTests.cs @@ -446,6 +446,22 @@ public void ViewModelValidator_AttemptToPassOldPaths(string path) } + [TestMethod] + public void ViewModelValidator_ServiceProvider() + { + var testViewModel = new TestViewModel8(); + var validator = CreateValidator(); + var expander = CreateErrorPathExpander(); + var modelState = new ModelState { ValidationTarget = testViewModel }; + + var errors = validator.ValidateViewModel(testViewModel).OrderBy(n => n.PropertyPath); + modelState.ErrorsInternal.AddRange(errors); + expander.Expand(modelState, testViewModel); + var results = modelState.Errors.OrderBy(n => n.PropertyPath).ToList(); + + Assert.AreEqual(0, results.Count); + } + public class TestViewModel : DotvvmViewModelBase { [Required] @@ -497,7 +513,7 @@ protected override ValidationResult IsValid(object value, ValidationContext vali var entity = (TestViewModel4Child)validationContext.ObjectInstance; if (entity.IsChecked && string.IsNullOrEmpty(entity.ConditionalRequired)) { - return new ValidationResult("Value is required when the field is checked!", new[] { validationContext.MemberName }); + return new ValidationResult("Value is required when the field is checked!", new[] { validationContext.MemberName }); } return base.IsValid(value, validationContext); @@ -542,6 +558,25 @@ public IEnumerable Validate(ValidationContext validationContex } } } - } + + public class TestViewModel8 + { + [ServiceProviderTest] + public int? Id { get; set; } + + public class ServiceProviderTestAttribute : ValidationAttribute + { + protected override ValidationResult IsValid(object value, ValidationContext validationContext) + { + if (validationContext.GetService() == null) + { + return new ValidationResult("Service provider is not available"); + } + + return ValidationResult.Success; + } + } + } + } }