aspnetcore icon indicating copy to clipboard operation
aspnetcore copied to clipboard

Missing IServiceProvider in ObjectGraphDataAnnotationsValidator

Open TheBigNeo opened this issue 1 year ago • 0 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Describe the bug

In the Validate function of an IValidatableObject model, no services can be loaded with GetRequiredService if Validate was triggered by ObjectGraphDataAnnotationsValidator.

The problem is that in ObjectGraphDataAnnotationsValidator.ValidateObject a new ValidationContext is created but the IServiceProvider is missing.

Source: https://github.com/dotnet/aspnetcore/tree/5da314644ae882ff22fb43101d0c3d89a35c40e9/src/Components/WebAssembly/Validation/src


This would fix the issue.

Class Microsoft.AspNetCore.Components.Forms.ObjectGraphDataAnnotationsValidator:

[Inject] public IServiceProvider ServiceProvider { get; set; }

private void ValidateObject(object value, HashSet<object> visited, List<ValidationResult> validationResults)
{
    var validationContext = new ValidationContext(value);
    validationContext.InitializeServiceProvider(type => ServiceProvider.GetService(type));
    validationContext.Items.Add(ValidationContextValidatorKey, this);
    validationContext.Items.Add(ValidatedObjectsKey,           visited);
    Validator.TryValidateObject(value, validationContext, validationResults, validateAllProperties: true);
}

  • Validate => System.ComponentModel.DataAnnotations.IValidatableObject.Validate
  • IValidatableObject => System.ComponentModel.DataAnnotations.IValidatableObject
  • GetRequiredService => Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T]
  • ObjectGraphDataAnnotationsValidator => Microsoft.AspNetCore.Components.Forms.ObjectGraphDataAnnotationsValidator

Expected Behavior

When calling GetRequiredService[T] in a model with IValidatableObject the service should be returned.

Steps To Reproduce

  • Start sample project
  • Hit Update button on Home page

Project: https://github.com/TheBigNeo/ObjectGraphDataAnnotationsValidator_ServiceProvider

Error Line: https://github.com/TheBigNeo/ObjectGraphDataAnnotationsValidator_ServiceProvider/blob/332b7ac50201309c97a2586a6dd2ef627017e1da/ObjectGraphDataAnnotationsValidator_ServiceProvider/Components/Sample/Animal.cs#L27

Exceptions (if any)

fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
      System.InvalidOperationException: No service for type 'ObjectGraphDataAnnotationsValidator_ServiceProvider.Components.Sample.IAnimalService' has been registered.
         at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
         at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
         at ObjectGraphDataAnnotationsValidator_ServiceProvider.Components.Sample.Friend.Validate(ValidationContext validationContext) in C:\Projects\RiderProjects\Sample\ObjectGraphDataAnnotationsValidator_ServiceProvider\ObjectGraphDataAnnotationsValidator_ServiceProvider\Components\Sample\Animal.cs:line 27
         at System.ComponentModel.DataAnnotations.Validator.GetObjectValidationErrors(Object instance, ValidationContext validationContext, Boolean validateAllProperties, Boolean breakOnFirstError)
         at System.ComponentModel.DataAnnotations.Validator.TryValidateObject(Object instance, ValidationContext validationContext, ICollection`1 validationResults, Boolean validateAllProperties)
         at Microsoft.AspNetCore.Components.Forms.ObjectGraphDataAnnotationsValidator.ValidateObject(Object value, HashSet`1 visited, List`1 validationResults)
         at Microsoft.AspNetCore.Components.Forms.ObjectGraphDataAnnotationsValidator.ValidateObject(Object value, HashSet`1 visited)
         at Microsoft.AspNetCore.Components.Forms.ObjectGraphDataAnnotationsValidator.ValidateObject(Object value, HashSet`1 visited)
         at Microsoft.AspNetCore.Components.Forms.ObjectGraphDataAnnotationsValidator.TryValidateRecursive(Object value, ValidationContext validationContext)
         at System.ComponentModel.DataAnnotations.ValidateComplexTypeAttribute.IsValid(Object value, ValidationContext validationContext)
         at System.ComponentModel.DataAnnotations.ValidationAttribute.GetValidationResult(Object value, ValidationContext validationContext)
         at System.ComponentModel.DataAnnotations.Validator.TryValidate(Object value, ValidationContext validationContext, ValidationAttribute attribute, ValidationError& validationError)
         at System.ComponentModel.DataAnnotations.Validator.GetValidationErrors(Object value, ValidationContext validationContext, IEnumerable`1 attributes, Boolean breakOnFirstError)
         at System.ComponentModel.DataAnnotations.Validator.GetObjectPropertyValidationErrors(Object instance, ValidationContext validationContext, Boolean validateAllProperties, Boolean breakOnFirstError)
         at System.ComponentModel.DataAnnotations.Validator.GetObjectValidationErrors(Object instance, ValidationContext validationContext, Boolean validateAllProperties, Boolean breakOnFirstError)
         at System.ComponentModel.DataAnnotations.Validator.TryValidateObject(Object instance, ValidationContext validationContext, ICollection`1 validationResults, Boolean validateAllProperties)
         at Microsoft.AspNetCore.Components.Forms.ObjectGraphDataAnnotationsValidator.ValidateObject(Object value, HashSet`1 visited, List`1 validationResults)
         at Microsoft.AspNetCore.Components.Forms.ObjectGraphDataAnnotationsValidator.ValidateObject(Object value, HashSet`1 visited)
         at Microsoft.AspNetCore.Components.Forms.ObjectGraphDataAnnotationsValidator.<OnInitialized>b__7_0(Object sender, ValidationRequestedEventArgs eventArgs)
         at Microsoft.AspNetCore.Components.Forms.EditContext.Validate()
         at Microsoft.AspNetCore.Components.Forms.EditForm.HandleSubmitAsync()
         at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
         at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
         at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
         at Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.<WaitForNonStreamingPendingTasks>g__Execute|38_0()
         at Microsoft.AspNetCore.Components.Endpoints.RazorComponentEndpointInvoker.RenderComponentCore(HttpContext context)
         at Microsoft.AspNetCore.Components.Endpoints.RazorComponentEndpointInvoker.RenderComponentCore(HttpContext context)
         at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.<>c.<<InvokeAsync>b__10_0>d.MoveNext()
      --- End of stack trace from previous location ---
         at Microsoft.AspNetCore.Antiforgery.Internal.AntiforgeryMiddleware.InvokeAwaited(HttpContext context)
         at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

.NET Version

8.0.400

Anything else?

The line to fix this bug comes from here: https://stackoverflow.com/a/63855575/1847143

dotnet --info

.NET SDK:
 Version:           8.0.400
 Commit:            36fe6dda56
 Workload version:  8.0.400-manifests.56cd0383
 MSBuild version:   17.11.3+0c8610977

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19045
 OS Platform: Windows
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\8.0.400\

.NET workloads installed:
Configured to use loose manifests when installing new manifests.
 [wasm-tools]
   Installation Source: SDK 8.0.400
   Manifest Version:    8.0.8/8.0.100
   Manifest Path:       C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.workload.mono.toolchain.current\8.0.8\WorkloadManifest.json
   Install Type:              Msi


Host:
  Version:      8.0.8
  Architecture: x64
  Commit:       08338fcaa5

.NET SDKs installed:
  8.0.102 [C:\Program Files\dotnet\sdk]
  8.0.300 [C:\Program Files\dotnet\sdk]
  8.0.302 [C:\Program Files\dotnet\sdk]
  8.0.400 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 8.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 8.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 8.0.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
  x86   [C:\Program Files (x86)\dotnet]
    registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
  Not set

global.json file:
  Not found

TheBigNeo avatar Aug 28 '24 15:08 TheBigNeo