Skip to content

fix(core): replace archived Blazored.FluentValidation with Blazilla - #993

Merged
sfmskywalker merged 7 commits into
mainfrom
claude/replace-blazored-fluentvalidation
Sep 7, 2026
Merged

fix(core): replace archived Blazored.FluentValidation with Blazilla#993
sfmskywalker merged 7 commits into
mainfrom
claude/replace-blazored-fluentvalidation

Conversation

@sfmskywalker

Copy link
Copy Markdown
Member

Purpose

Remove the unlisted, archived Blazored.FluentValidation dependency from Elsa.Studio.Core and migrate every form that used it to a maintained FluentValidation integration for Blazor, without weakening validation.

Scope

  • Dependency / build update
  • Bug fix (form submission ordering)

Description

Problem

Elsa.Studio.Core (and transitively the WebAssembly core package) depended on Blazored.FluentValidation 2.2.0. Every version of that package is unlisted on NuGet and its repository is archived, so consumers inherit an unfixable dependency and may fail restore where unlisted packages are disallowed.

Replacement

Blazilla 2.3.0 from LoreSoft: listed on NuGet, MIT, actively maintained (repository pushed this week, releases through 2.4.1), targets net8.0, net9.0, and net10.0, and depends on exactly the FluentValidation version this repo pins. 2.3.0 rather than 2.4.1 on purpose: 2.3.1 and later raise the Microsoft.AspNetCore.Components.Web floor above what this repo pins, which would force a Blazor runtime bump across all three target frameworks that this issue does not ask for. The diff between 2.3.0 and 2.4.1 is AOT and trimming annotations, an internal activation change, an extra overload, and dependency bumps; nothing used here changes. Upgrading later is a one-line dependency bump alongside the Components packages.

Forms

Six forms used the old validator component: the create and clone workflow dialogs, the input, output, and variable dialogs, and the create label dialog. Each now uses <FluentValidator> with a validator instance that exists before the validator component initializes. The old wrapper had an assembly-scanning fallback; the new one validates only through the supplied instance, so a missing instance would pass silently. That is why every form supplies one explicitly, and why the input dialog now constructs its edit context and validator before any await, as its sibling dialogs already did.

The create and clone dialogs hold the solution's only asynchronous rule, the workflow-name uniqueness check. Blazor decides OnValidSubmit from the synchronous validation result, which cannot see an in-flight async rule, so a native form submission (Enter in the name field) could create or clone before uniqueness resolved. Those two dialogs now submit through OnSubmit and await EditContext.ValidateAsync() on both the form and the button path. The other four forms have purely synchronous rules and keep OnValidSubmit; if an async rule is ever added to them FluentValidation throws rather than skipping it.

The metadata section of the workflow editor no longer references the old package on main (it constructs its validator directly and keys its form since #991); two tests pin that it enforces the required name and survives a parent re-render. The draft PR #935 explored this migration; its four review findings are addressed here, and it also bumped the whole Components family, which this change avoids.

Tests

WorkflowDialogValidationTests (16 tests): create and clone are blocked when the uniqueness rule resolves false and proceed when it resolves true, driven through both the form submission and the button, with the dialog asserted still open while validation is in flight; the input and output dialogs block an empty name and close on a valid one on both paths. Reverting the create and clone dialogs to OnValidSubmit fails exactly the two form-path cases. A shared controlled workflow-definition service stub serves these and the metadata tests.

Verification

  • dotnet build Elsa.Studio.sln: 0 errors, 0 new warnings.
  • dotnet test Elsa.Studio.sln: 1016 passed at the first commit; Elsa.Studio.Workflows.Tests now 225 passed.
  • git grep for the old package and its component name returns nothing across the tree, including hosts and docs.

Consumers that relied on the old package flowing transitively must switch to Blazilla's <FluentValidator>, which is the intent of this change.

Fixes #934

🤖 Generated with Claude Code

sfmskywalker and others added 3 commits September 7, 2026 14:56
Blazored.FluentValidation is unlisted on NuGet at every version and its
repository is archived, so Elsa.Studio.Core handed every consumer a
dependency that can never be fixed and that fails restore wherever
unlisted packages are disallowed. Blazilla is the maintained,
MIT-licensed equivalent and depends on exactly the FluentValidation
12.1.1 this repository already pins.

Blazilla only executes asynchronous rules when AsyncMode is set, and it
starts them from EditContext.Validate(), which returns before they
finish. The create and clone workflow dialogs hold the only asynchronous
rule in the solution - the workflow name uniqueness check - so both now
submit through OnSubmit and await EditContext.ValidateAsync() there,
which is what their Ok button already did. A native form submission
(Enter in the name field) would otherwise create or clone a workflow
under a name the uniqueness rule was about to reject. The other four
forms validate synchronously and keep OnValidSubmit.

Refs #934

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…er the output dialog; align the input dialog validator setup

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…newline

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Validator initialization, replaceable edit contexts, and stale asynchronous submissions can bypass validation or fail during rerenders.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Replaces the archived FluentValidation integration with Blazilla and updates workflow and label forms to preserve synchronous and asynchronous validation behavior.

Changes:

  • Replaces package references and Razor imports.
  • Migrates six dialogs to FluentValidator.
  • Adds workflow-dialog and metadata validation tests.
File summaries
File Description
Directory.Packages.props Pins Blazilla 2.3.0.
Elsa.Studio.sln.DotSettings Adds Blazilla to the dictionary.
src/framework/Elsa.Studio.Core/Elsa.Studio.Core.csproj Replaces the archived dependency.
src/modules/Elsa.Studio.Labels/_Imports.razor Imports Blazilla.
src/modules/Elsa.Studio.Labels/UI/Components/CreateLabelDialog.razor Migrates the label validator component.
src/modules/Elsa.Studio.Labels/UI/Components/CreateLabelDialog.razor.cs Uses EditContext.ValidateAsync.
src/modules/Elsa.Studio.Workflows/_Imports.razor Imports Blazilla.
src/modules/Elsa.Studio.Workflows/Components/WorkflowDefinitionList/CreateWorkflowDialog.razor Migrates create-form validation.
src/modules/Elsa.Studio.Workflows/Components/WorkflowDefinitionList/CreateWorkflowDialog.razor.cs Awaits asynchronous submission validation.
src/modules/Elsa.Studio.Workflows/Components/WorkflowDefinitionList/CloneWorkflowDialog.razor Migrates clone-form validation.
src/modules/Elsa.Studio.Workflows/Components/WorkflowDefinitionList/CloneWorkflowDialog.razor.cs Awaits asynchronous submission validation.
src/modules/Elsa.Studio.Workflows/Components/WorkflowDefinitionEditor/Components/WorkflowProperties/Tabs/InputOutput/Components/Inputs/EditInputDialog.razor Migrates input validation.
src/modules/Elsa.Studio.Workflows/Components/WorkflowDefinitionEditor/Components/WorkflowProperties/Tabs/InputOutput/Components/Inputs/EditInputDialog.razor.cs Initializes validation earlier and validates via EditContext.
src/modules/Elsa.Studio.Workflows/Components/WorkflowDefinitionEditor/Components/WorkflowProperties/Tabs/InputOutput/Components/Outputs/EditOutputDialog.razor Migrates output validation.
src/modules/Elsa.Studio.Workflows/Components/WorkflowDefinitionEditor/Components/WorkflowProperties/Tabs/InputOutput/Components/Outputs/EditOutputDialog.razor.cs Validates through EditContext.
src/modules/Elsa.Studio.Workflows/Components/WorkflowDefinitionEditor/Components/WorkflowProperties/Tabs/Variables/Components/EditVariableDialog.razor Migrates variable validation.
src/modules/Elsa.Studio.Workflows/Components/WorkflowDefinitionEditor/Components/WorkflowProperties/Tabs/Variables/Components/EditVariableDialog.razor.cs Validates through EditContext.
src/modules/Elsa.Studio.Workflows.Tests/WorkflowDialogValidationTests.cs Covers dialog submission paths.
src/modules/Elsa.Studio.Workflows.Tests/WorkflowDefinitionMetadataTests.cs Adds metadata validation regressions.
src/modules/Elsa.Studio.Workflows.Tests/Support/ControlledWorkflowDefinitionService.cs Provides controlled asynchronous test behavior.
Review details
  • Files reviewed: 20/20 changed files
  • Comments generated: 8
  • Review effort level: Balanced

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/modules/Elsa.Studio.Labels/UI/Components/CreateLabelDialog.razor Outdated
…stale asynchronous submissions

Guard CreateLabelDialog's form so it never renders before its validator is assigned,
key the five affected dialogs' EditForm by their EditContext to match the metadata
form's precedent for replaceable contexts, and make the create/clone workflow
dialogs discard a submission if the bound name changes while the asynchronous
uniqueness check is still pending.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Label submission can bypass validation while initialization is pending, and input-dialog rerenders now repeat remote descriptor requests.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 20/20 changed files
  • Comments generated: 2
  • Review effort level: Balanced

… load input descriptors once

CreateLabelDialog's Ok button stayed clickable while its FluentValidator
was still loading, letting an empty label through since ValidateAsync()
found no attached validator. EditInputDialog moved its descriptor loads
into OnParametersSetAsync, causing the storage-driver and variable-type
services to be re-fetched on every parent parameter update instead of once.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Async validation races can bypass uniqueness checks, and the input dialog permits submission before required descriptors finish loading.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 20/20 changed files
  • Comments generated: 3
  • Review effort level: Balanced

…gate the input dialog on loaded descriptors

Guard the input dialog's submit paths behind a flag that only flips once the
descriptor lookups have populated the model, closing the window where a
non-empty name could reach OnValidSubmit before Type/StorageDriver/UIHint
were set. Make the create and clone workflow dialogs decide submission from
a component-owned validator call instead of EditContext.ValidateAsync(),
whose shared message store could be overwritten by a stale Blazilla
field-change validation resolving after the submit's own check.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The custom validation store can retain or publish stale workflow-name errors after the field changes.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 21/21 changed files
  • Comments generated: 1
  • Review effort level: Balanced

…hen the name changes

Turn the static WorkflowMetadataValidation helper into an instance-scoped
WorkflowMetadataSubmitValidator owned by each dialog's edit context. It now
discards a validation result whose name no longer matches the model (instead
of publishing it and letting the caller check afterward), and it clears its
own message store on EditContext.OnFieldChanged so a duplicate-name message
does not linger once the user edits the field, since Blazilla's field-change
handler only clears its own store.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approved

The migration preserves validation behavior, addresses asynchronous submission races, and includes focused regression coverage.

Review details
  • Files reviewed: 21/21 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@sfmskywalker
sfmskywalker merged commit c6dfcab into main Sep 7, 2026
9 checks passed
@sfmskywalker
sfmskywalker deleted the claude/replace-blazored-fluentvalidation branch September 7, 2026 14:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Blazored.FluentValidation dependency (v2.2.0) is unlisted on NuGet and its source repo is archived

2 participants