Remove FluentValidation dependency, use plain .NET validation

Replace AbstractValidator-based request validators with a small
IModelValidator<T>/ValidationResult pattern (ported from BuyEngine's
Common namespace), wired into the MVC pipeline via a
ModelValidationActionFilter so controllers and response shape are
unaffected. Also copy over the Guard precondition helper.
This commit is contained in:
2026-07-05 21:57:35 -07:00
parent 127aefc020
commit bdc85a1f3a
23 changed files with 361 additions and 130 deletions

View File

@@ -1,11 +1,10 @@
using System.Text;
using System.Threading.RateLimiting;
using FluentValidation;
using FluentValidation.AspNetCore;
using MicCheck.Api.Common.Security.ApiKeys;
using MicCheck.Api.Audit;
using MicCheck.Api.Common.Security.Authentication;
using MicCheck.Api.Common.Security.Authorization;
using MicCheck.Api.Common.Validation;
using MicCheck.Api.Data;
using MicCheck.Api.Environments;
using MicCheck.Api.Features;
@@ -42,7 +41,7 @@ try
.WriteTo.Console());
builder.Services.AddOpenApi();
builder.Services.AddControllers()
builder.Services.AddControllers(options => options.Filters.Add<ModelValidationActionFilter>())
.AddJsonOptions(options =>
options.JsonSerializerOptions.Converters.Add(
new System.Text.Json.Serialization.JsonStringEnumConverter()));
@@ -92,20 +91,11 @@ try
limiter.QueueLimit = 0;
}));
builder.Services.AddFluentValidationAutoValidation();
builder.Services.AddValidatorsFromAssemblyContaining<Program>();
builder.Services.AddModelValidatorsFromAssemblyContaining<Program>();
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
var errors = context.ModelState
.Where(e => e.Value?.Errors.Count > 0)
.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value!.Errors.Select(e => e.ErrorMessage).ToArray());
return new UnprocessableEntityObjectResult(new { errors });
};
options.InvalidModelStateResponseFactory = context => ValidationProblemResponseFactory.Create(context.ModelState);
});
builder.Services.AddMemoryCache();