Coder Social home page Coder Social logo

dreamescaper / fluentvalidation.blazor Goto Github PK

View Code? Open in Web Editor NEW

This project forked from ryanelian/fluentvalidation.blazor

0.0 2.0 0.0 465 KB

Fluent Validation-powered Blazor component for validating standard <EditForm> :milky_way: :white_check_mark:

Home Page: https://www.nuget.org/packages/Accelist.FluentValidation.Blazor

License: MIT License

C# 99.77% HTML 0.23%

fluentvalidation.blazor's Introduction

FluentValidation.Blazor

Fluent Validation-powered Blazor component for validating standard <EditForm> ๐ŸŒ€ โœ…

GitHub Actions NuGet

Install

dotnet add package FluentValidation
dotnet add package Accelist.FluentValidation.Blazor

Getting Started

This library is a direct replacement to the default Blazor <DataAnnotationValidator> with zero configuration required โšก in the application code base:

<EditForm Model="Form">


    <FluentValidator></FluentValidator>


    <div class="form-group">
        <label for="email">Email</label>
        <InputText id="email" type="email" class="form-control" @bind-Value="Form.Email"></InputText>
        <ValidationMessage For="() => Form.Email"></ValidationMessage>
    </div>
    <div class="form-group">
        <button type="submit" class="btn btn-primary">
            <i class="fas fa-chevron-up"></i>
            Submit
        </button>
    </div>
</EditForm>
@code {
    FormModel Form = new FormModel();
}
public class FormModel
{
    public string Email { set; get; }
}

public class FormModelValidator : AbstractValidator<FormModel>
{
    public FormModelValidator()
    {
        RuleFor(Q => Q.Email).NotEmpty().EmailAddress().MaximumLength(255);
    }
}

The <FluentValidator> component automatically detects the Model data type used by the parent <EditForm> then attempts to acquire the corresponding FluentValidation.IValidator<T> for that model data type.

For this reason, in addition to coding the usual FluentValidation.AbstractValidator<T> Fluent Validation implementation, you are required to register the FluentValidation.IValidator<T> implementation in the Startup.cs Service Provider (Dependency Injection):

services.AddTransient<IValidator<CreateAccountFormModel>, CreateAccountFormModelValidator>();
// Alternatively, use FluentValidation.DependencyInjectionExtensions package (read further down below...)

This effectively allows you, dear programmer, to inject required services to your validation implementations for writing amazing custom validation methods! ๐Ÿ”ฅ

public class FormModelValidator : AbstractValidator<FormModel>
{
    readonly AppDbContext DB;
    readonly IServiceProvider SP;

    public FormModelValidator(AppDbContext db, IServiceProvider sp)
    {
        this.DB = db;
        this.SP = sp;

        RuleFor(Q => Q.Email).NotEmpty().EmailAddress().MaximumLength(255)
            .Must(BeUniqueEmail).WithMessage("Email address is already registered.");
    }

    bool BeUniqueEmail(string email)
    {
        var exist = DB.Account.Where(Q => Q.Email == email).Any();
        return (exist == false);
    }
}

Inlined Validator

Validator parameter may also be passed directly to the component to inline the AbstractValidator implementation instead of relying on .NET Core DI:

<FluentValidator Validator="Validator"></FluentValidator>
@code {
    FormModelValidator Validator = new FormModelValidator();
}

FluentValidation.DependencyInjectionExtensions

dotnet add package FluentValidation.DependencyInjectionExtensions
services.AddValidatorsFromAssemblyContaining<Program>();

Can be used to auto-populate all validators from current application / other project automatically!

Nested Objects & Arrays Validation

FluentValidation offers SetValidator method for validating nested objects and arrays. Combined with Dependency Injection capability of this component library, a complex form can be validated easily:

public class RootValidator : AbstractValidator<Root>
{
    public RootValidator(IValidator<Child> childValidator, IValidator<Item> itemValidator)
    {
        RuleFor(Q => Q.Child).SetValidator(childValidator);
        RuleForEach(Q => Q.ArrayOfItems).SetValidator(itemValidator); // Array, List, IList, ...
    }
}

The validators used MUST be registered in the ASP.NET Core service provider!

If for some reason Dependency Injection is not possible, the parameter ChildValidators (inlined Dictionary<Type, IValidator> defining validators used for each children model types) MUST be passed into the component due to technical reasons.

Repeated Remote Call Warning โš ๏ธ

By default, Fluent Validation does NOT short-circuit the validation chain on first error.

This may cause performance issues when a validation logic hits the database / remote service multiple times in short burst due to validation triggers on field change!

To reduce the impact of repeated custom validation calls, use:

  • .Cascade(CascadeMode.Stop) after RuleFor() chain,

  • Or set ValidatorOptions.CascadeMode = CascadeMode.Stop; on Program.cs application entry point.

Why Not Just Use <DataAnnotationValidator>?

  1. <DataAnnotationValidator> cannot use DI services at the moment...

  2. ... but <DataAnnotationValidator> also cannot do AddModelError() like Razor Pages. Which rules out validation AFTER form submission!

  3. [ValidationAttribute] top-level IsValid() method cannot be async!

fluentvalidation.blazor's People

Contributors

ryanelian avatar sfmskywalker avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.