From 32fce98b63cdc59719c1de8df99cf4e7fc67c382 Mon Sep 17 00:00:00 2001 From: Marco Minerva Date: Mon, 5 May 2025 15:06:22 +0200 Subject: [PATCH] Add FluentValidation for Question model validation - Updated `AskEndpoints.cs` to include `MinimalHelpers.FluentValidation` and standardize endpoint descriptions. - Integrated FluentValidation in `Program.cs` and registered validators. - Modified `SqlDatabaseVectorSearch.csproj` to add necessary package references for FluentValidation. - Created `QuestionValidator` class to enforce validation rules on the `Question` model. --- SqlDatabaseVectorSearch/Endpoints/AskEndpoints.cs | 8 +++++--- SqlDatabaseVectorSearch/Program.cs | 4 ++++ .../SqlDatabaseVectorSearch.csproj | 2 ++ .../Validators/QuestionValidator.cs | 12 ++++++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 SqlDatabaseVectorSearch/Validators/QuestionValidator.cs diff --git a/SqlDatabaseVectorSearch/Endpoints/AskEndpoints.cs b/SqlDatabaseVectorSearch/Endpoints/AskEndpoints.cs index 12abe24..1976fe7 100644 --- a/SqlDatabaseVectorSearch/Endpoints/AskEndpoints.cs +++ b/SqlDatabaseVectorSearch/Endpoints/AskEndpoints.cs @@ -1,5 +1,5 @@ - -using System.ComponentModel; +using System.ComponentModel; +using MinimalHelpers.FluentValidation; using SqlDatabaseVectorSearch.Models; using SqlDatabaseVectorSearch.Services; @@ -10,11 +10,12 @@ public class AskEndpoints : IEndpointRouteHandlerBuilder public static void MapEndpoints(IEndpointRouteBuilder endpoints) { endpoints.MapPost("/api/ask", async (Question question, VectorSearchService vectorSearchService, CancellationToken cancellationToken, - [Description("If true, the question will be reformulated taking into account the context of the chat identified by the given ConversationId.")] bool reformulate = true) => + [Description("If true, the question will be reformulated taking into account the context of the chat identified by the given ConversationId.")] bool reformulate = true) => { var response = await vectorSearchService.AskQuestionAsync(question, reformulate, cancellationToken); return TypedResults.Ok(response); }) + .WithValidation() .WithSummary("Asks a question") .WithDescription("The question will be reformulated taking into account the context of the chat identified by the given ConversationId.") .WithTags("Ask"); @@ -35,6 +36,7 @@ public class AskEndpoints : IEndpointRouteHandlerBuilder return Stream(); }) + .WithValidation() .WithSummary("Asks a question and gets the response as streaming") .WithDescription("The question will be reformulated taking into account the context of the chat identified by the given ConversationId.") .WithTags("Ask"); diff --git a/SqlDatabaseVectorSearch/Program.cs b/SqlDatabaseVectorSearch/Program.cs index 8a194ba..5a3feab 100644 --- a/SqlDatabaseVectorSearch/Program.cs +++ b/SqlDatabaseVectorSearch/Program.cs @@ -1,5 +1,6 @@ using System.Net.Mime; using System.Text.Json.Serialization; +using FluentValidation; using Microsoft.EntityFrameworkCore; using Microsoft.SemanticKernel; using SqlDatabaseVectorSearch.Components; @@ -82,6 +83,9 @@ builder.Services.AddOpenApi(options => options.AddDefaultProblemDetailsResponse(); }); +ValidatorOptions.Global.LanguageManager.Enabled = false; +builder.Services.AddValidatorsFromAssemblyContaining(); + builder.Services.AddDefaultProblemDetails(); builder.Services.AddDefaultExceptionHandler(); diff --git a/SqlDatabaseVectorSearch/SqlDatabaseVectorSearch.csproj b/SqlDatabaseVectorSearch/SqlDatabaseVectorSearch.csproj index 4e899aa..dc0daae 100644 --- a/SqlDatabaseVectorSearch/SqlDatabaseVectorSearch.csproj +++ b/SqlDatabaseVectorSearch/SqlDatabaseVectorSearch.csproj @@ -12,6 +12,7 @@ + @@ -25,6 +26,7 @@ + diff --git a/SqlDatabaseVectorSearch/Validators/QuestionValidator.cs b/SqlDatabaseVectorSearch/Validators/QuestionValidator.cs new file mode 100644 index 0000000..538f654 --- /dev/null +++ b/SqlDatabaseVectorSearch/Validators/QuestionValidator.cs @@ -0,0 +1,12 @@ +using FluentValidation; +using SqlDatabaseVectorSearch.Models; + +namespace SqlDatabaseVectorSearch.Validators; + +public class QuestionValidator : AbstractValidator +{ + public QuestionValidator() + { + RuleFor(x => x.Text).NotEmpty().MaximumLength(4096).WithName("Question Text"); + } +}