Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation
Use FluentValidation rules instead of ComponentModel attributes
https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation
Last synced: 3 months ago
JSON representation
Use FluentValidation rules instead of ComponentModel attributes
- Host: GitHub
- URL: https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation
- Owner: micro-elements
- License: mit
- Created: 2018-03-19T19:23:35.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2023-12-23T19:43:25.000Z (about 1 year ago)
- Last Synced: 2024-04-14T09:03:48.597Z (9 months ago)
- Language: C#
- Homepage:
- Size: 462 KB
- Stars: 357
- Watchers: 12
- Forks: 52
- Open Issues: 27
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-dotnet-core - MicroElements.Swashbuckle.FluentValidation - Adds FluentValidation rules to swagger. (Frameworks, Libraries and Tools / API)
- fucking-awesome-dotnet-core - MicroElements.Swashbuckle.FluentValidation - Adds FluentValidation rules to swagger. (Frameworks, Libraries and Tools / API)
- awesome-dotnet-core - MicroElements.Swashbuckle.FluentValidation - Adds FluentValidation rules to swagger. (Frameworks, Libraries and Tools / API)
- awesome-dotnet-core - MicroElements.Swashbuckle.FluentValidation - 向Swagger添加FluentValidation规则。 (框架, 库和工具 / API)
README
# MicroElements.Swashbuckle.FluentValidation
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
[![License](https://img.shields.io/github/license/micro-elements/MicroElements.Swashbuckle.FluentValidation.svg)](https://raw.githubusercontent.com/micro-elements/MicroElements.Swashbuckle.FluentValidation/master/LICENSE)
[![NuGetVersion](https://img.shields.io/nuget/v/MicroElements.Swashbuckle.FluentValidation.svg)](https://www.nuget.org/packages/MicroElements.Swashbuckle.FluentValidation)
![NuGetDownloads](https://img.shields.io/nuget/dt/MicroElements.Swashbuckle.FluentValidation.svg)
[![MyGetVersion](https://img.shields.io/myget/micro-elements/v/MicroElements.Swashbuckle.FluentValidation.svg)](https://www.myget.org/feed/micro-elements/package/nuget/MicroElements.Swashbuckle.FluentValidation)![Build and publish](https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation/workflows/Build%20and%20publish/badge.svg)
[![AppVeyor](https://img.shields.io/appveyor/ci/micro-elements/microelements-swashbuckle-fluentvalidation.svg?logo=appveyor)](https://ci.appveyor.com/project/micro-elements/microelements-swashbuckle-fluentvalidation)
[![Coverage Status](https://img.shields.io/coveralls/micro-elements/MicroElements.Swashbuckle.FluentValidation.svg)](https://coveralls.io/r/micro-elements/MicroElements.Swashbuckle.FluentValidation)[![Gitter](https://img.shields.io/gitter/room/micro-elements/MicroElements.Swashbuckle.FluentValidation.svg)](https://gitter.im/micro-elements/MicroElements.Swashbuckle.FluentValidation)
### Supporting the project
MicroElements.Swashbuckle.FluentValidation is developed and supported by [@petriashev](https://github.com/petriashev) for free in his spare time.
If you find MicroElements.Swashbuckle.FluentValidation useful, please consider financially supporting the project via [OpenCollective](https://opencollective.com/micro-elements) which will help keep the project going 🙏.## Usage
### 1. Minimal API
#### MinimalApi.csproj
```xml
net7.0
enable
enable
```
#### Program.cs
```csharp
using FluentValidation;
using FluentValidation.AspNetCore;
using MicroElements.Swashbuckle.FluentValidation.AspNetCore;var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;// Asp.Net stuff
services.AddControllers();
services.AddEndpointsApiExplorer();// Add Swagger
services.AddSwaggerGen();// Add FV
services.AddFluentValidationAutoValidation();
services.AddFluentValidationClientsideAdapters();// Add FV validators
services.AddValidatorsFromAssemblyContaining();// Add FV Rules to swagger
services.AddFluentValidationRulesToSwagger();var app = builder.Build();
// Use Swagger
app.UseSwagger();
app.UseSwaggerUI();app.MapControllers();
app.Run();
```### 2. AspNetCore WebApi
#### Reference packages in your web project
```xml
```
#### Change Startup.cs
```csharp
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Asp.net stuff
services.AddControllers();
// HttpContextValidatorRegistry requires access to HttpContext
services.AddHttpContextAccessor();// Register FV validators
services.AddValidatorsFromAssemblyContaining(lifetime: ServiceLifetime.Scoped);// Add FV to Asp.net
services.AddFluentValidationAutoValidation();// Add swagger
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});// [Optional] Add INameResolver (SystemTextJsonNameResolver will be registered by default)
// services.AddSingleton();// Adds FluentValidationRules staff to Swagger. (Minimal configuration)
services.AddFluentValidationRulesToSwagger();// [Optional] Configure generation options for your needs. Also can be done with services.Configure
// services.AddFluentValidationRulesToSwagger(options =>
// {
// options.SetNotNullableIfMinLengthGreaterThenZero = true;
// options.UseAllOffForMultipleRules = true;
// });// Adds logging
services.AddLogging(builder => builder.AddConsole());
}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseRouting();app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});// Adds swagger
app.UseSwagger();// Adds swagger UI
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
}
```## Version compatibility
| MicroElements.Swashbuckle.FluentValidation | Swashbuckle.AspNetCore | FluentValidation |
|--------------------------------------------|------------------------|------------------|
| [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 by `FluentValidationRules.CreateDefaultRules()`List or default rules:
* Required
* NotEmpty
* Length
* Pattern
* Comparison
* BetweenExample of rule:
```csharp
new FluentValidationRule("Pattern")
{
Matches = propertyValidator => propertyValidator is IRegularExpressionValidator,
Apply = context =>
{
var regularExpressionValidator = (IRegularExpressionValidator)context.PropertyValidator;
context.Schema.Properties[context.PropertyKey].Pattern = regularExpressionValidator.Expression;
}
},
```## Samples
### Swagger Sample model and validator
```csharp
public class Sample
{
public string PropertyWithNoRules { get; set; }public string NotNull { get; set; }
public string NotEmpty { get; set; }
public string EmailAddress { get; set; }
public string RegexField { get; set; }public int ValueInRange { get; set; }
public int ValueInRangeExclusive { get; set; }public float ValueInRangeFloat { get; set; }
public double ValueInRangeDouble { get; set; }
}public class SampleValidator : AbstractValidator
{
public SampleValidator()
{
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 numbers
RuleFor(sample => sample.ValueInRangeFloat).InclusiveBetween(1.1f, 5.3f);
RuleFor(sample => sample.ValueInRangeDouble).ExclusiveBetween(2.2, 7.5f);
}
}
```### Swagger Sample model screenshot
![SwaggerSample](image/swagger_sample.png "SwaggerSample")
### Validator with Include
```csharp
public class CustomerValidator : AbstractValidator
{
public CustomerValidator()
{
RuleFor(customer => customer.Surname).NotEmpty();
RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");Include(new CustomerAddressValidator());
}
}internal class CustomerAddressValidator : AbstractValidator
{
public CustomerAddressValidator()
{
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' from root provider because it requires scoped service 'TDependency'`
Workarounds in order or preference:
#### Workaround 1 (Use HttpContextServiceProviderValidatorFactory) by @WarpSpideR
```csharp
public void ConfigureServices(IServiceCollection services)
{
// HttpContextServiceProviderValidatorFactory requires access to HttpContext
services.AddHttpContextAccessor();services
.AddMvc()
// Adds fluent validators to Asp.net
.AddFluentValidation(c =>
{
c.RegisterValidatorsFromAssemblyContaining();
// Optionally set validator factory if you have problems with scope resolve inside validators.
c.ValidatorFactoryType = typeof(HttpContextServiceProviderValidatorFactory);
});
```#### Workaround 2 (Use ScopedSwaggerMiddleware)
Replace `UseSwagger` for `UseScopedSwagger`:
```csharp
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app
.UseMvc()
// Use scoped swagger if you have problems with scoped services in validators
.UseScopedSwagger();
```#### Workaround 3 (Set ValidateScopes to false)
```csharp
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
// Needed for using scoped services (for example DbContext) in validators
.UseDefaultServiceProvider(options => options.ValidateScopes = false)
.UseStartup()
.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 with `internal` and use `Include` to include other validation rules to one "Main" validator.
## Problem: I'm using `FluentValidation` or `FluentValidation.DependencyInjectionExtensions` instead of `FluentValidation.AspNetCore`
If you are using the more basic `FluentValidation` or `FluentValidation.DependencyInjectionExtensions` libraries, then they will not automatically register `IValidatorFactory` and you will get an error at runtime: "ValidatorFactory is not provided. Please register FluentValidation." In that case you must register it manually (see [issue 97](https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation/issues/97) for more details):
````cs
services.TryAddTransient();
services.AddFluentValidationRulesToSwagger();
````## Problem: Newtonsoft.Json DefaultNamingStrategy, SnakeCaseNamingStrategy does not work
```csharp
Startup.cs:
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = new NewtonsoftJsonNamingPolicy(new SnakeCaseNamingStrategy());
//options.JsonSerializerOptions.DictionaryKeyPolicy = new NewtonsoftJsonNamingPolicy(new SnakeCaseNamingStrategy());
})///
/// Allows use Newtonsoft as System.Text .
///
public class NewtonsoftJsonNamingPolicy : JsonNamingPolicy
{
private readonly NamingStrategy _namingStrategy;///
/// Creates new instance of .
///
/// Newtonsoft naming strategy.
public NewtonsoftJsonNamingPolicy(NamingStrategy namingStrategy)
{
_namingStrategy = namingStrategy;
}///
public override string ConvertName(string name)
{
return _namingStrategy.GetPropertyName(name, false);
}
}
```## Credits
Initial version of this project was based on
[Mujahid Daud Khan](https://stackoverflow.com/users/1735196/mujahid-daud-khan) answer on StackOverflow:
https://stackoverflow.com/questions/44638195/fluent-validation-with-swagger-in-asp-net-core/49477995#49477995