From 9ae7c65b06741434b3457c95fc45a6bcfac0673f Mon Sep 17 00:00:00 2001 From: Felix Winterhalter Date: Wed, 10 Dec 2025 15:44:10 +0100 Subject: [PATCH] fix: Non-Nullable String empty query parameter Fixes: https://github.com/JasperFx/wolverine/issues/1924 --- ...Bug_1924_NonNullableEmptyQueryParameter.cs | 60 +++++++++++++++++++ .../Wolverine.Http/CodeGen/IReadHttpFrame.cs | 2 +- 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/Http/Wolverine.Http.Tests/Bugs/Bug_1924_NonNullableEmptyQueryParameter.cs diff --git a/src/Http/Wolverine.Http.Tests/Bugs/Bug_1924_NonNullableEmptyQueryParameter.cs b/src/Http/Wolverine.Http.Tests/Bugs/Bug_1924_NonNullableEmptyQueryParameter.cs new file mode 100644 index 000000000..10afb0747 --- /dev/null +++ b/src/Http/Wolverine.Http.Tests/Bugs/Bug_1924_NonNullableEmptyQueryParameter.cs @@ -0,0 +1,60 @@ +using Alba; +using IntegrationTests; +using Marten; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Wolverine.Marten; + +namespace Wolverine.Http.Tests.Bugs; + +public class Bug_1924_NonNullableEmptyQueryParameter +{ + [Fact] + public async Task non_nullable_empty_string_query_parameters_dont_throw() + { + var builder = WebApplication.CreateBuilder([]); + + builder.Services.AddMarten(opts => + { + // Establish the connection string to your Marten database + opts.Connection(Servers.PostgresConnectionString); + opts.DisableNpgsqlLogging = true; + }).IntegrateWithWolverine(); + + builder.Host.UseWolverine(opts => + { + opts.Discovery.DisableConventionalDiscovery().IncludeType(); + opts.ApplicationAssembly = GetType().Assembly; + }); + + builder.Services.AddWolverineHttp(); + + // This is using Alba, which uses WebApplicationFactory under the covers + await using var host = await AlbaHost.For(builder, app => { app.MapWolverineEndpoints(); }); + + await host.Scenario(x => + { + x.Get.Url("/bugs/1924/nullable?first=Test"); + x.StatusCodeShouldBe(200); + x.ContentShouldBe("Test"); + }); + + await host.Scenario(x => + { + x.Get.Url("/bugs/1924/nullable"); + x.StatusCodeShouldBe(200); + x.ContentShouldBe(""); + }); + } +} + +public class Bug1924Controller +{ + [WolverineGet("/bugs/1924/nullable", Name = "Bug1924_nullable")] + public string Get([FromQuery] string first) + { + if (first == null) throw new ArgumentNullException(nameof(first)); + return first.ToString(); + } +} diff --git a/src/Http/Wolverine.Http/CodeGen/IReadHttpFrame.cs b/src/Http/Wolverine.Http/CodeGen/IReadHttpFrame.cs index 8fb8da59c..7c74bbeef 100644 --- a/src/Http/Wolverine.Http/CodeGen/IReadHttpFrame.cs +++ b/src/Http/Wolverine.Http/CodeGen/IReadHttpFrame.cs @@ -109,7 +109,7 @@ private void writeStringValue(ISourceWriter writer, GeneratedMethod method) { var assignTo = Mode == AssignMode.WriteToVariable ? $"var {Variable.Usage}" : _property; - writer.Write($"{assignTo} = {rawValueSource()};"); + writer.Write($"{assignTo} = {rawValueSource()}?.ToString() {(_isNullable ? "" : "?? \"\"")};"); if (_source == BindingSource.RouteValue) {