ServiceStack.Validation combined with FluentValidation package

Hi. Is there any easy way to use my existing implementation of my API validators (implemented using ServiceStack.Validation) in my Blazor project where I would like to use Accelist.FluentValidation.Blazor package for forms validation?

I was thinking to create some abstract class which combines both packages but not sure is it good approach.

public abstract class CustomAbstractValidator : ServiceStack.FluentValidation.AbstractValidator, FluentValidation.IValidator

I don’t expect Blazor would be able to reference any ServiceStack Server libraries like ServiceStack.dll’s that your abstract class solution expects to use. If it’s source compatible you would need to use conditional compilation symbols to remove ServiceStack Server references and add any Blazor references in your .csproj and all your .cs source files to reference the correct namespace, e.g. something like:

#if BLAZOR //Using compilation symbol in your Blazor build
using Accelist.FluentValidation.Blazor;
#else
using ServiceStack.FluentValidation;
#endif

Otherwise you could explore source based solutions, e.g. a script to copy Validators source files into a blazor project that replaces ServiceStack.FluentValidation references with Accelist.FluentValidation.Blazor.

You also may be able to enable code sharing with careful use of Partial classes with common code in 1 file and impl specific classes e.g. inheriting AbstractValidator would be in impl specific classes:

  • Validators.cs
  • Validators.Blazor.cs
  • Validators.ServiceStack.cs

Then you could use conditional compilation symbols or csproj to stub out the other implementation .cs, e.g:

<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.1'">
    <Compile Remove="**/*.ServiceStack.cs" />
    <None Include="**/*.ServiceStack.cs" />
</ItemGroup>

Not sure if Blazor has its own tfm yet or if they’re still using netstandard2.1

1 Like

@mythz, thanks for answer I am also review other option:

Since I use WebAssembly approach I can use DataAnnotations for validation rules which can be really run on the client without touching server api. Of course drawback of this approach is code duplication.

So I have:

  1. Crud Patch DTO

    public class PatchEstimate : Estimate, IPatchDb, IReturn, IHasResponseStatus
    {
    public ResponseStatus ResponseStatus { get; set; }
    }

  2. Entity

    public class Estimate
    {
    [AutoIncrement]
    public int Id { get; set; }

     [System.ComponentModel.DataAnnotations.Required]
     [System.ComponentModel.DataAnnotations.StringLength(8, ErrorMessage = "Name length can't be more than 8.")]
     public string Name { get; set; }
    

}

  1. ServiceStack Validator

    public class PatchEstimateValidator : AbstractValidator
    {
    public PatchEstimateValidator()
    {
    RuleFor(s => s.Name)
    .NotEmpty(); // here some more validation rules touching Db and other services
    }
    }

  2. Client side form with validation support





                     <DataAnnotationsValidator />
    
                     <MudTextField @bind-Value="vm.Name" Immediate="true" Label="Estimate name" For="@(() => vm.Name)" />
                     <ValidationMessage For="() => vm.Name"></ValidationMessage>
    
                     <MudRadioGroup @bind-SelectedOption="@vm.EstimateType">
                         <MudRadio Option="@(EstimateType.Offer)" Color="Color.Primary">Offer</MudRadio>
                         <MudRadio Option="@(EstimateType.Additionals)" Color="Color.Secondary">Additional</MudRadio>
                     </MudRadioGroup>
    
                     <MudText>Filename: @estimate.EstimateFileFileName</MudText>
                     <ValidationSummary />
    
                 </MudCardContent>
             </MudCard>
         </DialogContent>
         <DialogActions>
             <MudButton OnClick="Cancel">Cancel</MudButton>
             <MudButton Color="Color.Primary" ButtonType="ButtonType.Submit">Ok</MudButton>
         </DialogActions>
     </MudDialog>
    

Another approach may be to use Declarative Validation which will be emitted in the DTOs as Generic Validator Attributes which you could use reflection to parse on the client and execute corresponding custom validation logic.

Or you could use custom code feature to generate validation attributes that works in Blazor.