Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Use FluentValidation rules instead of ComponentModel attributes

License

NotificationsYou must be signed in to change notification settings

micro-elements/MicroElements.Swashbuckle.FluentValidation

Repository files navigation

Use FluentValidation rules instead of ComponentModel attributes to define swagger schema.

Note: For WebApi see:https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation.WebApi

Statuses

LicenseNuGetVersionNuGetDownloadsMyGetVersion

Build and publishAppVeyorCoverage Status

Gitter

Supporting the project

MicroElements.Swashbuckle.FluentValidation is developed and supported by@petriashev for free in his spare time.If you find MicroElements.Swashbuckle.FluentValidation useful, please consider financially supporting the project viaOpenCollective which will help keep the project going 🙏.

Usage

1. Minimal API

MinimalApi.csproj

<ProjectSdk="Microsoft.NET.Sdk.Web">    <PropertyGroup>        <TargetFramework>net7.0</TargetFramework>        <Nullable>enable</Nullable>        <ImplicitUsings>enable</ImplicitUsings>    </PropertyGroup>    <ItemGroup>        <PackageReferenceInclude="FluentValidation.AspNetCore"Version="11.2.2" />        <PackageReferenceInclude="MicroElements.Swashbuckle.FluentValidation"Version="6.0.0" />        <PackageReferenceInclude="Microsoft.AspNetCore.OpenApi"Version="7.0.2" />        <PackageReferenceInclude="Swashbuckle.AspNetCore"Version="6.4.0" />    </ItemGroup>    </Project>

Program.cs

usingFluentValidation;usingFluentValidation.AspNetCore;usingMicroElements.Swashbuckle.FluentValidation.AspNetCore;varbuilder=WebApplication.CreateBuilder(args);varservices=builder.Services;// Asp.Net stuffservices.AddControllers();services.AddEndpointsApiExplorer();// Add Swaggerservices.AddSwaggerGen();// Add FVservices.AddFluentValidationAutoValidation();services.AddFluentValidationClientsideAdapters();// Add FV validatorsservices.AddValidatorsFromAssemblyContaining<Program>();// Add FV Rules to swaggerservices.AddFluentValidationRulesToSwagger();varapp=builder.Build();// Use Swaggerapp.UseSwagger();app.UseSwaggerUI();app.MapControllers();app.Run();

2. AspNetCore WebApi

Reference packages in your web project

<PackageReferenceInclude="FluentValidation.AspNetCore"Version="11.1.0" /><PackageReferenceInclude="MicroElements.Swashbuckle.FluentValidation"Version="6.0.0" /><PackageReferenceInclude="Swashbuckle.AspNetCore"Version="6.3.0" />

Change Startup.cs

// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){// Asp.net stuffservices.AddControllers();// HttpContextValidatorRegistry requires access to HttpContextservices.AddHttpContextAccessor();// Register FV validatorsservices.AddValidatorsFromAssemblyContaining<Startup>(lifetime:ServiceLifetime.Scoped);// Add FV to Asp.netservices.AddFluentValidationAutoValidation();// Add swaggerservices.AddSwaggerGen(c=>{c.SwaggerDoc("v1",newOpenApiInfo{Title="My API",Version="v1"});});// [Optional] Add INameResolver (SystemTextJsonNameResolver will be registered by default)// services.AddSingleton<INameResolver, CustomNameResolver>();// Adds FluentValidationRules staff to Swagger. (Minimal configuration)services.AddFluentValidationRulesToSwagger();// [Optional] Configure generation options for your needs. Also can be done with services.Configure<SchemaGenerationOptions>// services.AddFluentValidationRulesToSwagger(options =>// {//     options.SetNotNullableIfMinLengthGreaterThenZero = true;//     options.UseAllOffForMultipleRules = true;// });// Adds loggingservices.AddLogging(builder=>builder.AddConsole());}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironmentenv){app.UseRouting();app.UseEndpoints(endpoints=>{endpoints.MapControllers();});// Adds swaggerapp.UseSwagger();// Adds swagger UIapp.UseSwaggerUI(c=>{c.SwaggerEndpoint("/swagger/v1/swagger.json","My API V1");});}

Version compatibility

MicroElements.Swashbuckle.FluentValidationSwashbuckle.AspNetCoreFluentValidation
[1.1.0, 2.0.0)[3.0.0, 4.0.0)>=7.2.0
[2.0.0, 3.0.0)[4.0.0, 5.0.0)>=8.1.3
[3.0.0, 3.1.0)[5.0.0, 5.2.0)>=8.3.0
[3.1.0, 4.2.1)[5.2.0, 6.0.0)>=8.3.0
[4.2.0, 5.0.0)[5.5.1, 7.0.0)[9.0.0, 10)
[5.0.0, 6.0.0)[6.3.0, 7.0.0)[10.0.0, 12)

Sample application

See sample project:https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation/tree/master/samples/SampleWebApi

Supported validators

  • INotNullValidator (NotNull)
  • INotEmptyValidator (NotEmpty)
  • ILengthValidator (for strings: Length, MinimumLength, MaximumLength, ExactLength) (for arrays: MinItems, MaxItems)
  • IRegularExpressionValidator (Email, Matches)
  • IComparisonValidator (GreaterThan, GreaterThanOrEqual, LessThan, LessThanOrEqual)
  • IBetweenValidator (InclusiveBetween, ExclusiveBetween)

Extensibility

You can register FluentValidationRule in ServiceCollection.

User defined rule name replaces default rule with the same.Full list of default rules can be get byFluentValidationRules.CreateDefaultRules()

List or default rules:

  • Required
  • NotEmpty
  • Length
  • Pattern
  • Comparison
  • Between

Example of rule:

newFluentValidationRule("Pattern"){Matches= propertyValidator=>propertyValidatorisIRegularExpressionValidator,Apply= context=>{varregularExpressionValidator=(IRegularExpressionValidator)context.PropertyValidator;context.Schema.Properties[context.PropertyKey].Pattern=regularExpressionValidator.Expression;}},

Samples

Swagger Sample model and validator

publicclassSample{publicstringPropertyWithNoRules{get;set;}publicstringNotNull{get;set;}publicstringNotEmpty{get;set;}publicstringEmailAddress{get;set;}publicstringRegexField{get;set;}publicintValueInRange{get;set;}publicintValueInRangeExclusive{get;set;}publicfloatValueInRangeFloat{get;set;}publicdoubleValueInRangeDouble{get;set;}}publicclassSampleValidator:AbstractValidator<Sample>{publicSampleValidator(){RuleFor(sample=>sample.NotNull).NotNull();RuleFor(sample=>sample.NotEmpty).NotEmpty();RuleFor(sample=>sample.EmailAddress).EmailAddress();RuleFor(sample=>sample.RegexField).Matches(@"(\d{4})-(\d{2})-(\d{2})");RuleFor(sample=>sample.ValueInRange).GreaterThanOrEqualTo(5).LessThanOrEqualTo(10);RuleFor(sample=>sample.ValueInRangeExclusive).GreaterThan(5).LessThan(10);// WARNING: Swashbuckle implements minimum and maximim as int so you will loss fraction part of float and double numbersRuleFor(sample=>sample.ValueInRangeFloat).InclusiveBetween(1.1f,5.3f);RuleFor(sample=>sample.ValueInRangeDouble).ExclusiveBetween(2.2,7.5f);}}

Swagger Sample model screenshot

SwaggerSample

Validator with Include

publicclassCustomerValidator:AbstractValidator<Customer>{publicCustomerValidator(){RuleFor(customer=>customer.Surname).NotEmpty();RuleFor(customer=>customer.Forename).NotEmpty().WithMessage("Please specify a first name");Include(newCustomerAddressValidator());}}internalclassCustomerAddressValidator:AbstractValidator<Customer>{publicCustomerAddressValidator(){RuleFor(customer=>customer.Address).Length(20,250);}}

Get params bounded to validatable models

MicroElements.Swashbuckle.FluentValidation updates swagger schema for operation parameters bounded to validatable models.

Defining rules dynamically from database

See BlogValidator in sample.

Common problems and workarounds

Error:System.InvalidOperationException: 'Cannot resolve 'IValidator<T>' from root provider because it requires scoped service 'TDependency'

Workarounds in order or preference:

Workaround 1 (Use HttpContextServiceProviderValidatorFactory) by @WarpSpideR

publicvoidConfigureServices(IServiceCollectionservices){// HttpContextServiceProviderValidatorFactory requires access to HttpContextservices.AddHttpContextAccessor();services.AddMvc()// Adds fluent validators to Asp.net.AddFluentValidation(c=>{c.RegisterValidatorsFromAssemblyContaining<Startup>();// Optionally set validator factory if you have problems with scope resolve inside validators.c.ValidatorFactoryType=typeof(HttpContextServiceProviderValidatorFactory);});

Workaround 2 (Use ScopedSwaggerMiddleware)

ReplaceUseSwagger forUseScopedSwagger:

publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironmentenv){app.UseMvc()// Use scoped swagger if you have problems with scoped services in validators.UseScopedSwagger();

Workaround 3 (Set ValidateScopes to false)

publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args)// Needed for using scoped services (for example DbContext) in validators.UseDefaultServiceProvider(options=>options.ValidateScopes=false).UseStartup<Startup>().Build();

Problem: I cant use several validators of one type

Example: You split validator into several small validators but AspNetCore uses only one of them.

Workaround: Hide dependent validators withinternal and useInclude to include other validation rules to one "Main" validator.

Problem: I'm usingFluentValidation orFluentValidation.DependencyInjectionExtensions instead ofFluentValidation.AspNetCore

If you are using the more basicFluentValidation orFluentValidation.DependencyInjectionExtensions libraries, then they will not automatically registerIValidatorFactory and you will get an error at runtime: "ValidatorFactory is not provided. Please register FluentValidation." In that case you must register it manually (seeissue 97 for more details):

services.TryAddTransient<IValidatorFactory,ServiceProviderValidatorFactory>();services.AddFluentValidationRulesToSwagger();

Problem: Newtonsoft.Json DefaultNamingStrategy, SnakeCaseNamingStrategy does not work

Startup.cs:.AddJsonOptions(options=>{options.JsonSerializerOptions.PropertyNamingPolicy=newNewtonsoftJsonNamingPolicy(newSnakeCaseNamingStrategy());//options.JsonSerializerOptions.DictionaryKeyPolicy = new NewtonsoftJsonNamingPolicy(new SnakeCaseNamingStrategy());})/// <summary>/// Allows use Newtonsoft <see cref="NamingStrategy"/> as System.Text <see cref="JsonNamingPolicy"/>./// </summary>publicclassNewtonsoftJsonNamingPolicy:JsonNamingPolicy{privatereadonlyNamingStrategy_namingStrategy;/// <summary>/// Creates new instance of <see cref="NewtonsoftJsonNamingPolicy"/>./// </summary>/// <param name="namingStrategy">Newtonsoft naming strategy.</param>publicNewtonsoftJsonNamingPolicy(NamingStrategynamingStrategy){_namingStrategy=namingStrategy;}/// <inheritdoc />publicoverridestringConvertName(stringname){return_namingStrategy.GetPropertyName(name,false);}}

Credits

Initial version of this project was based onMujahid Daud Khan answer on StackOverflow:https://stackoverflow.com/questions/44638195/fluent-validation-with-swagger-in-asp-net-core/49477995#49477995

About

Use FluentValidation rules instead of ComponentModel attributes

Resources

License

Stars

Watchers

Forks

Sponsor this project

  •  

Packages

No packages published

Contributors22


[8]ページ先頭

©2009-2025 Movatter.jp