Skip to content

Instantly share code, notes, and snippets.

@asabla
Created February 16, 2023 17:08
Show Gist options
  • Save asabla/7cdbc53662821d78e48c178b0da52ea0 to your computer and use it in GitHub Desktop.
Save asabla/7cdbc53662821d78e48c178b0da52ea0 to your computer and use it in GitHub Desktop.
Fluent Configuration validation example in .net 7 and web api
using System.ComponentModel.DataAnnotations;
namespace DotnetConsoles.Configuration.Api;
public class ApiSettings
{
[Required, Url, MinLength(10), ]
public string WebhookUrl { get; set; } = null!;
[Required, MinLength(3)]
public string DisplayName { get; set; } = null!;
public bool Enabled { get; set; }
[Required]
public SubSettings SubSettings { get; set; } = null!;
}
public class SubSettings
{
[Required]
public string CoolName { get; set; } = null!;
}
using FluentValidation;
namespace DotnetConsoles.Configuration.Api.Validation;
public class ApiSettingsValidator : AbstractValidator<ApiSettings>
{
public ApiSettingsValidator()
{
RuleFor(setting => setting.WebhookUrl)
.NotNull().NotEmpty()
.MinimumLength(10)
.Must(StringMustBeUri);
RuleFor(setting => setting.DisplayName)
.NotNull().NotEmpty()
.MinimumLength(3);
RuleFor(setting => setting.SubSettings)
.NotNull().NotEmpty();
}
private static bool StringMustBeUri(string arg)
{
return Uri.TryCreate(arg, UriKind.Absolute, out var resultUri)
&& resultUri.Scheme == Uri.UriSchemeHttps;
}
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentValidation" Version="11.4.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
</Project>
using DotnetConsoles.Configuration.Api.Validation;
namespace DotnetConsoles.Configuration.Api.Extensions;
public static class ConfigurationExtensions
{
public static WebApplicationBuilder ConfigurationSetup(this WebApplicationBuilder builder)
{
// Configuration setup
builder.Configuration
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", true, true);
// Validate configuration on startup
builder.Services.AddOptions<ApiSettings>()
.BindConfiguration(nameof(ApiSettings))
.ValidateDataAnnotations()
.Validate(v =>
v.WebhookUrl.StartsWith("https://"),
$"{nameof(ApiSettings.WebhookUrl)} must start with https://")
.ValidateOnStart();
// Fluent validation alternative
builder.Services.AddOptions<ApiSettings>()
.BindConfiguration(nameof(ApiSettings))
.Validate(v =>
{
var validator = new ApiSettingsValidator();
return validator.Validate(v).IsValid;
})
.ValidateOnStart();
return builder;
}
}
using DotnetConsoles.Configuration.Api.Endpoints;
using DotnetConsoles.Configuration.Api.Extensions;
var builder = WebApplication.CreateBuilder(args);
// Load and setup configurations
builder.ConfigurationSetup();
// Security settings
app.UseHttpsRedirection();
app.Run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment