diff --git a/src/Http/Wolverine.Http.Marten/CompiledQueryWriterPolicy.cs b/src/Http/Wolverine.Http.Marten/CompiledQueryWriterPolicy.cs index 30a5e8552..e6ff355bb 100644 --- a/src/Http/Wolverine.Http.Marten/CompiledQueryWriterPolicy.cs +++ b/src/Http/Wolverine.Http.Marten/CompiledQueryWriterPolicy.cs @@ -2,6 +2,7 @@ using JasperFx.CodeGeneration.Frames; using JasperFx.CodeGeneration.Model; using JasperFx.Core.Reflection; +using Marten; using Marten.Linq; using Wolverine.Http.Resources; using QueryableExtensions = Marten.AspNetCore.QueryableExtensions; @@ -31,17 +32,51 @@ public bool TryApply(HttpChain chain) if (compiledQueryClosure is null) return false; var arguments = compiledQueryClosure.GetGenericArguments(); + + // If we're dealing with a primitive return type we need to write its string representation directly + if (arguments[1].IsPrimitive) + { + // This call runs the query + var queryCall = + typeof(MartenQueryMethodCall<,>).CloseAndBuildAs(result, arguments); + chain.Postprocessors.Add(queryCall); - var methodCall = typeof(MartenWriteArrayMethodCall<,>).CloseAndBuildAs(result, (_responseType, _successStatusCode), arguments); + // This call writes the response directly to the HttpContext as a string + var writeStringCall = MethodCall.For(handler => HttpHandler.WriteString(null!, "")); + writeStringCall.Arguments[1] = new Variable(queryCall.ReturnVariable!.VariableType, + $"{queryCall.ReturnVariable.Usage}.ToString()", queryCall); + chain.Postprocessors.Add(writeStringCall); + } + else + { + + var writeJsonCall = + typeof(MartenWriteJsonToStreamMethodCall<,>).CloseAndBuildAs(result, + (_responseType, _successStatusCode), arguments); + chain.Postprocessors.Add(writeJsonCall); + } - chain.Postprocessors.Add(methodCall); return true; } } -public class MartenWriteArrayMethodCall : MethodCall +public class MartenQueryMethodCall : MethodCall +{ + public MartenQueryMethodCall(Variable resultVariable) : base(typeof(IDocumentSession), FindMethod()) + { + Arguments[0] = resultVariable; + } + + static MethodInfo FindMethod() + { + return ReflectionHelper.GetMethod(x => + x.QueryAsync((ICompiledQuery)null!, default))!; + } +} + +public class MartenWriteJsonToStreamMethodCall : MethodCall { - public MartenWriteArrayMethodCall(Variable resultVariable, (string responseType, int successStatusCode) options) : base(typeof(QueryableExtensions), FindMethod(resultVariable)) + public MartenWriteJsonToStreamMethodCall(Variable resultVariable, (string responseType, int successStatusCode) options) : base(typeof(QueryableExtensions), FindMethod(resultVariable)) { Arguments[1] = resultVariable; Arguments[3] = Constant.ForString(options.responseType); diff --git a/src/Http/Wolverine.Http.Tests/Marten/compiled_query_writer.cs b/src/Http/Wolverine.Http.Tests/Marten/compiled_query_writer.cs index 6aa186044..d4e624aa2 100644 --- a/src/Http/Wolverine.Http.Tests/Marten/compiled_query_writer.cs +++ b/src/Http/Wolverine.Http.Tests/Marten/compiled_query_writer.cs @@ -43,6 +43,28 @@ public async Task endpoint_returning_compiled_list_query_should_return_query_res approvedInvoiceList.ShouldNotBeNull(); approvedInvoiceList.Count.ShouldBe(approvedInvoices); } + + [Fact] + public async Task endpoint_returning_compiled_primitive_query_should_return_query_result() + { + await using var session = Store.LightweightSession(); + int invoicesCount = 5; + for (int i = 0; i < invoicesCount; i++) + { + var invoice = + new Invoice() + { + }; + session.Store(invoice); + } + + await session.SaveChangesAsync(); + + var approvedInvoiceList = await Host.GetAsText("/invoices/compiled/count"); + approvedInvoiceList.ShouldNotBeNull(); + int.TryParse(approvedInvoiceList, out var result).ShouldBeTrue(); + result.ShouldBe(invoicesCount); + } [Fact] public async Task endpoint_returning_compiled_query_should_return_query_result() diff --git a/src/Http/WolverineWebApi/Internal/Generated/WolverineHandlers/GET_invoices_compiled_count.cs b/src/Http/WolverineWebApi/Internal/Generated/WolverineHandlers/GET_invoices_compiled_count.cs new file mode 100644 index 000000000..a8ceefd35 --- /dev/null +++ b/src/Http/WolverineWebApi/Internal/Generated/WolverineHandlers/GET_invoices_compiled_count.cs @@ -0,0 +1,47 @@ +// +#pragma warning disable +using Microsoft.AspNetCore.Routing; +using System; +using System.Linq; +using Wolverine.Http; +using Wolverine.Marten.Publishing; +using Wolverine.Runtime; + +namespace Internal.Generated.WolverineHandlers +{ + // START: GET_invoices_compiled_count + public class GET_invoices_compiled_count : Wolverine.Http.HttpHandler + { + private readonly Wolverine.Http.WolverineHttpOptions _wolverineHttpOptions; + private readonly Wolverine.Runtime.IWolverineRuntime _wolverineRuntime; + private readonly Wolverine.Marten.Publishing.OutboxedSessionFactory _outboxedSessionFactory; + + public GET_invoices_compiled_count(Wolverine.Http.WolverineHttpOptions wolverineHttpOptions, Wolverine.Runtime.IWolverineRuntime wolverineRuntime, Wolverine.Marten.Publishing.OutboxedSessionFactory outboxedSessionFactory) : base(wolverineHttpOptions) + { + _wolverineHttpOptions = wolverineHttpOptions; + _wolverineRuntime = wolverineRuntime; + _outboxedSessionFactory = outboxedSessionFactory; + } + + + + public override async System.Threading.Tasks.Task Handle(Microsoft.AspNetCore.Http.HttpContext httpContext) + { + var messageContext = new Wolverine.Runtime.MessageContext(_wolverineRuntime); + // Building the Marten session + await using var documentSession = _outboxedSessionFactory.OpenSession(messageContext); + + // The actual HTTP request handler execution + var compiledCountQuery = WolverineWebApi.Marten.InvoicesEndpoint.GetCompiledCount(); + + var result_of_QueryAsync = await documentSession.QueryAsync(compiledCountQuery, httpContext.RequestAborted).ConfigureAwait(false); + await Wolverine.Http.HttpHandler.WriteString(httpContext, result_of_QueryAsync.ToString()).ConfigureAwait(false); + } + + } + + // END: GET_invoices_compiled_count + + +} + diff --git a/src/Http/WolverineWebApi/Marten/Documents.cs b/src/Http/WolverineWebApi/Marten/Documents.cs index 40efe2a71..e628654e1 100644 --- a/src/Http/WolverineWebApi/Marten/Documents.cs +++ b/src/Http/WolverineWebApi/Marten/Documents.cs @@ -70,6 +70,12 @@ public static ByIdCompiled GetCompiled(Guid id) { return new ByIdCompiled(id); } + + [WolverineGet("/invoices/compiled/count")] + public static CompiledCountQuery GetCompiledCount() + { + return new CompiledCountQuery(); + } } public class Invoice @@ -104,4 +110,12 @@ public ByIdCompiled(Guid id) { return q => q.FirstOrDefault(x => x.Id == Id); } -} \ No newline at end of file +} + +public class CompiledCountQuery : ICompiledQuery +{ + public Expression, int>> QueryIs() + { + return q => q.Count(); + } +}