Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] FluentValidation never removed on FluentValidationValidator unloaded #155 #163

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using FluentValidation;
using System.Collections.Concurrent;
using FluentValidation;
using FluentValidation.Internal;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -11,6 +12,8 @@ public static class EditContextFluentValidationExtensions
private static readonly char[] Separators = { '.', '[' };
private static readonly List<string> ScannedAssembly = new();
private static readonly List<AssemblyScanResult> AssemblyScanResults = new();
private static readonly ConcurrentDictionary<EditContext, EventHandler<ValidationRequestedEventArgs>> ValidationRequestedHandlers = new();
private static readonly ConcurrentDictionary<EditContext, EventHandler<FieldChangedEventArgs>> FieldChangedHandlers = new();
public const string PendingAsyncValidation = "AsyncValidationTask";

public static void AddFluentValidation(this EditContext editContext, IServiceProvider serviceProvider, bool disableAssemblyScanning, IValidator? validator, FluentValidationValidator fluentValidationValidator)
Expand All @@ -19,11 +22,32 @@ public static void AddFluentValidation(this EditContext editContext, IServicePro

var messages = new ValidationMessageStore(editContext);

editContext.OnValidationRequested +=
async (sender, _) => await ValidateModel((EditContext)sender!, messages, serviceProvider, disableAssemblyScanning, fluentValidationValidator, validator);
EventHandler<ValidationRequestedEventArgs> validationRequestedHandler
= async (sender, _) => await ValidateModel((EditContext)sender!, messages, serviceProvider, disableAssemblyScanning, fluentValidationValidator, validator);
if (ValidationRequestedHandlers.TryAdd(editContext, validationRequestedHandler))
editContext.OnValidationRequested += validationRequestedHandler;

editContext.OnFieldChanged +=
async (_, eventArgs) => await ValidateField(editContext, messages, eventArgs.FieldIdentifier, serviceProvider, disableAssemblyScanning, validator);
EventHandler<FieldChangedEventArgs> fieldChangedHandler
= async (_, eventArgs) => await ValidateField(editContext, messages, eventArgs.FieldIdentifier, serviceProvider, disableAssemblyScanning, validator);
if (FieldChangedHandlers.TryAdd(editContext, fieldChangedHandler))
editContext.OnFieldChanged += fieldChangedHandler;
}

public static void RemoveFluentValidation(this EditContext editContext)
{
ArgumentNullException.ThrowIfNull(editContext, nameof(editContext));

if (ValidationRequestedHandlers.TryGetValue(editContext, out var validationRequestedHandler))
{
editContext.OnValidationRequested -= validationRequestedHandler;
ValidationRequestedHandlers.TryRemove(editContext, out _);
}

if (FieldChangedHandlers.TryGetValue(editContext, out var fieldChangedHandler))
{
editContext.OnFieldChanged -= fieldChangedHandler;
FieldChangedHandlers.TryRemove(editContext, out _);
}
}

private static async Task ValidateModel(EditContext editContext,
Expand Down
23 changes: 22 additions & 1 deletion src/Blazored.FluentValidation/FluentValidationsValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Blazored.FluentValidation;

public class FluentValidationValidator : ComponentBase
public class FluentValidationValidator : ComponentBase, IDisposable
{
[Inject] private IServiceProvider ServiceProvider { get; set; } = default!;

Expand Down Expand Up @@ -81,4 +81,25 @@ protected override void OnInitialized()

CurrentEditContext.AddFluentValidation(ServiceProvider, DisableAssemblyScanning, Validator, this);
}

private bool _disposedValue;
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
CurrentEditContext?.RemoveFluentValidation();
}

_disposedValue = true;
}
}

public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}