简体   繁体   English

在 Asp.net Core 中使用 Swagger 进行流畅验证

[英]Fluent Validation with Swagger in Asp.net Core

I am currently using Fluent Validation instead of Data Annotations for my Web api and using swagger for API documentation.我目前在 Web api 中使用Fluent Validation而不是Data Annotations ,并在 API 文档中使用 swagger。 Fluent validation rules are not reflected in swagger model as i am unable to configure fluent validation rules with swagger schema filter.流畅的验证规则未反映在 swagger 模型中,因为我无法使用 swagger 模式过滤器配置流畅的验证规则。

This Blog has a good explanation for using it with ASP.net MVC. 这个博客对在 ASP.net MVC 中使用它有很好的解释。 but i am unable to configure it to use it in ASP.net Core.但我无法配置它以在 ASP.net Core 中使用它。

So far i have tried the following code but i am unable to get validator type.到目前为止,我已经尝试了以下代码,但我无法获得验证器类型。

services.AddSwaggerGen(options => options.SchemaFilter<AddFluentValidationRules>());

public class AddFluentValidationRules : ISchemaFilter
{
    public void Apply(Schema model, SchemaFilterContext context)
    {
        model.Required = new List<string>();
        var validator = GetValidator(type); // How?
        var validatorDescriptor = validator.CreateDescriptor();

        foreach (var key in model.Properties.Keys)
        {
            foreach (var propertyValidator in validatorDescriptor.GetValidatorsForMember(key))
            {
                 // Add to model properties as in blog
            }
        }
    }
}

I've created github project and nuget package based on Mujahid Daud Khan answer.我已经根据 Mujahid Daud Khan 的回答创建了 github 项目和 nuget 包。 I made redesign to support extensibility and supported other validators.我进行了重新设计以支持可扩展性并支持其他验证器。

github: https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation github: https : //github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation

nuget: https://www.nuget.org/packages/MicroElements.Swashbuckle.FluentValidation nuget: https ://www.nuget.org/packages/MicroElements.Swashbuckle.FluentValidation

Note: For WebApi see: https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation.WebApi注意:对于 WebApi,请参阅: https : //github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation.WebApi

Supported validators支持的验证器

  • INotNullValidator (NotNull) INotNullValidator (NotNull)
  • INotEmptyValidator (NotEmpty) INotEmptyValidator (NotEmpty)
  • ILengthValidator (Length, MinimumLength, MaximumLength, ExactLength) ILengthValidator(长度、最小长度、最大长度、精确长度)
  • IRegularExpressionValidator (Email, Matches) IRegularExpressionValidator(电子邮件,匹配)
  • IComparisonValidator (GreaterThan, GreaterThanOrEqual, LessThan, LessThanOrEqual) IComparisonValidator(GreaterThan、GreaterThanOrEqual、LessThan、LessThanOrEqual)
  • IBetweenValidator (InclusiveBetween, ExclusiveBetween) IBetweenValidator (InclusiveBetween, ExclusiveBetween)

Usage用法

1. Reference packages in your web project: 1.在你的web项目中引用包:

<PackageReference Include="FluentValidation.AspNetCore" Version="7.5.2" />
<PackageReference Include="MicroElements.Swashbuckle.FluentValidation" Version="0.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="2.3.0" />

2. Change Startup.cs 2.更改Startup.cs

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services
        .AddMvc()
        // Adds fluent validators to Asp.net
        .AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<CustomerValidator>());

    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
        // Adds fluent validation rules to swagger
        c.AddFluentValidationRules();
    });
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app
        .UseMvc()
        // Adds swagger
        .UseSwagger();

    // Adds swagger UI
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
    });
}

Swagger Sample model and validator Swagger 示例模型和验证器

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 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);
    }
}

Feel free to add issues!随意添加问题!

After searching i have finally figured out that i needed to IValidationFactory for validator instance.搜索后,我终于发现我需要IValidationFactory验证器实例。

public class AddFluentValidationRules : ISchemaFilter
{
    private readonly IValidatorFactory _factory;

    /// <summary>
    ///     Default constructor with DI
    /// </summary>
    /// <param name="factory"></param>
    public AddFluentValidationRules(IValidatorFactory factory)
    {
        _factory = factory;
    }

    /// <summary>
    /// </summary>
    /// <param name="model"></param>
    /// <param name="context"></param>
    public void Apply(Schema model, SchemaFilterContext context)
    {

        // use IoC or FluentValidatorFactory to get AbstractValidator<T> instance
        var validator = _factory.GetValidator(context.SystemType);
        if (validator == null) return;
        if (model.Required == null)
            model.Required = new List<string>();

        var validatorDescriptor = validator.CreateDescriptor();
        foreach (var key in model.Properties.Keys)
        {
            foreach (var propertyValidator in validatorDescriptor
                .GetValidatorsForMember(ToPascalCase(key)))
            {
                if (propertyValidator is NotNullValidator 
                  || propertyValidator is NotEmptyValidator)
                    model.Required.Add(key);

                if (propertyValidator is LengthValidator lengthValidator)
                {
                    if (lengthValidator.Max > 0)
                        model.Properties[key].MaxLength = lengthValidator.Max;

                    model.Properties[key].MinLength = lengthValidator.Min;
                }

                if (propertyValidator is RegularExpressionValidator expressionValidator)
                    model.Properties[key].Pattern = expressionValidator.Expression;

                // Add more validation properties here;
            }
        }
    }

    /// <summary>
    ///     To convert case as swagger may be using lower camel case
    /// </summary>
    /// <param name="inputString"></param>
    /// <returns></returns>
    private static string ToPascalCase(string inputString)
    {
        // If there are 0 or 1 characters, just return the string.
        if (inputString == null) return null;
        if (inputString.Length < 2) return inputString.ToUpper();
        return inputString.Substring(0, 1).ToUpper() + inputString.Substring(1);
    }
}

and add this class to swaggerGen options并将此类添加到 swaggerGen 选项

options.SchemaFilter<AddFluentValidationRules>();
  1. Install Nuget package: MicroElements.Swashbuckle.FluentValidation安装 Nuget 包: MicroElements.Swashbuckle.FluentValidation

  2. Add to ConfigureServices: services.AddFluentValidationRulesToSwagger();添加到配置services.AddFluentValidationRulesToSwagger();services.AddFluentValidationRulesToSwagger();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM