Use FluentValidation rules to define validation requirements for NSwag Swagger/OpenAPI schema.
This project has been split into two packages.
HttpContextServiceProviderValidatorFactory
for supporting HttpContext scoped services when using FluentValidation with DB Context validators.dotnet add package ZymLabs.NSwag.FluentValidation.AspNetCore
Or if you want to use the core package for your application without the AspNetCore MVC dependencies.
dotnet add package ZymLabs.NSwag.FluentValidation
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// HttpContextServiceProviderValidatorFactory requires access to HttpContext
services.AddHttpContextAccessor();
services
.AddControllers()
// 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);
})
services.AddOpenApiDocument((settings, serviceProvider) =>
{
var fluentValidationSchemaProcessor = serviceProvider.CreateScope().ServiceProvider.GetService<FluentValidationSchemaProcessor>();
// Add the fluent validations schema processor
settings.SchemaProcessors.Add(fluentValidationSchemaProcessor);
});
// Add the FluentValidationSchemaProcessor as a scoped service
services.AddScoped<FluentValidationSchemaProcessor>(provider =>
{
var validationRules = provider.GetService<IEnumerable<FluentValidationRule>>();
var loggerFactory = provider.GetService<ILoggerFactory>();
return new FluentValidationSchemaProcessor(provider, validationRules, loggerFactory);
});
}
ZymLabs.NSwag.FluentValidation | Swashbuckle.AspNetCore | FluentValidation |
---|---|---|
[0.1.0, 0.4.0) | [13.0.0, 14.0.0) | >=7.2.0 |
[0.4.0, 0.5.0) | [13.0.0, 14.0.0) | >=10.0.0 |
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:
Example of rule:
new FluentValidationRule("Pattern")
{
Matches = propertyValidator => propertyValidator is IRegularExpressionValidator,
Apply = context =>
{
var regularExpressionValidator = (IRegularExpressionValidator)context.PropertyValidator;
context.Schema.Properties[context.PropertyKey].Pattern = regularExpressionValidator.Expression;
}
},
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<Sample>
{
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);
RuleFor(sample => sample.ValueInRangeFloat).InclusiveBetween(1.1f, 5.3f);
RuleFor(sample => sample.ValueInRangeDouble).ExclusiveBetween(2.2, 7.5f);
}
}
public class CustomerValidator : AbstractValidator<Customer>
{
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<Customer>
{
public CustomerAddressValidator()
{
RuleFor(customer => customer.Address).Length(20, 250);
}
}
To 0.6.0
Update the dependency injection to specify the constructor to use as there is now ambiguity with the other constructor.
System.InvalidOperationException
Unable to activate type 'ZymLabs.NSwag.FluentValidation.FluentValidationSchemaProcessor'. The following constructors are ambiguous:
Void .ctor(System.IServiceProvider, System.Collections.Generic.IEnumerable`1[ZymLabs.NSwag.FluentValidation.FluentValidationRule], Microsoft.Extensions.Logging.ILoggerFactory)
Void .ctor(FluentValidation.IValidatorFactory, System.Collections.Generic.IEnumerable`1[ZymLabs.NSwag.FluentValidation.FluentValidationRule], Microsoft.Extensions.Logging.ILoggerFactory)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)
From:
serviceCollection.AddScoped<FluentValidationSchemaProcessor>();
To:
serviceCollection.AddScoped<FluentValidationSchemaProcessor>(provider =>
{
var validationRules = provider.GetService<IEnumerable<FluentValidationRule>>();
var loggerFactory = provider.GetService<ILoggerFactory>();
return new FluentValidationSchemaProcessor(provider, validationRules, loggerFactory);
});
This project is a port of MicroElements.Swashbuckle.FluentValidation to NSwag. The initial version of this project was based on Mujahid Daud Khan answer on StackOverflow: https://stackoverflow.com/questions/44638195/fluent-validation-with-swagger-in-asp-net-core/49477995#49477995