diff --git a/src/Http/Routing/src/Builder/EndpointRouteBuilderExtensions.cs b/src/Http/Routing/src/Builder/EndpointRouteBuilderExtensions.cs index ab00f5ff2749..4c1cb9b09904 100644 --- a/src/Http/Routing/src/Builder/EndpointRouteBuilderExtensions.cs +++ b/src/Http/Routing/src/Builder/EndpointRouteBuilderExtensions.cs @@ -38,6 +38,11 @@ public static IEndpointConventionBuilder MapGet( string pattern, RequestDelegate requestDelegate) { + var returnType = requestDelegate.Method.ReturnType; + if (returnType is { IsGenericType: true } && returnType.GetGenericTypeDefinition() == typeof(Task<>)) + { + return MapMethods(endpoints, pattern, GetVerb, requestDelegate as Delegate); + } return MapMethods(endpoints, pattern, GetVerb, requestDelegate); } diff --git a/src/Http/Routing/test/UnitTests/Builder/RequestDelegateEndpointRouteBuilderExtensionsTest.cs b/src/Http/Routing/test/UnitTests/Builder/RequestDelegateEndpointRouteBuilderExtensionsTest.cs index cf2e1cca9f43..a76b96a19be5 100644 --- a/src/Http/Routing/test/UnitTests/Builder/RequestDelegateEndpointRouteBuilderExtensionsTest.cs +++ b/src/Http/Routing/test/UnitTests/Builder/RequestDelegateEndpointRouteBuilderExtensionsTest.cs @@ -1,10 +1,15 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO.Pipelines; using System.Linq.Expressions; +using System.Text; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing.Patterns; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Moq; namespace Microsoft.AspNetCore.Builder; @@ -69,6 +74,30 @@ public void MapEndpoint_StringPattern_BuildsEndpoint() Assert.Equal("/", endpointBuilder1.RoutePattern.RawText); } + [Fact] + public async Task MapEndpoint_ReturnGenericTypeTask_GeneratedDelegate() + { + var httpContext = new DefaultHttpContext(); + var responseBodyStream = new MemoryStream(); + httpContext.Response.Body = responseBodyStream; + + // Arrange + var builder = new DefaultEndpointRouteBuilder(Mock.Of()); + static async Task GenericTypeTaskDelegate(HttpContext context) => await Task.FromResult("String Test"); + + // Act + var endpointBuilder = builder.MapGet("/", GenericTypeTaskDelegate); + + // Assert + var endpointBuilder1 = GetRouteEndpointBuilder(builder); + var requestDelegate = endpointBuilder1.RequestDelegate; + await requestDelegate(httpContext); + + var responseBody = Encoding.UTF8.GetString(responseBodyStream.ToArray()); + + Assert.Equal("String Test", responseBody); + } + [Fact] public void MapEndpoint_TypedPattern_BuildsEndpoint() {