-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Closed
dotnet/runtime
#85506Labels
NativeAOTfeature-routingneeds-area-labelUsed by the dotnet-issue-labeler to label those issues which couldn't be triaged automaticallyUsed by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically
Description
Using MapShortCircuit in an app that's published native AOT results in an exception on first request when the endpoint itself is built:
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HMQ7EGDA44U5", Request id "0HMQ7EGDA44U5:00000001": An unhandled exception was thrown by the application.
System.NotSupportedException: Cannot retrieve a MethodInfo for this delegate because the method it targeted (Microsoft.AspNetCore.Routing.RouteShortCircuitEndpointRouteBuilderExtensions.<>c.<.cctor>b__3_0(HttpContext)) was not enabled for metadata.
at Internal.Reflection.Extensions.NonPortable.DelegateMethodInfoRetriever.GetDelegateMethodInfo(Delegate) + 0x34f
at Microsoft.AspNetCore.Routing.RouteEndpointDataSource.CreateRouteEndpointBuilder(RouteEndpointDataSource.RouteEntry, RoutePattern, IReadOnlyList`1, IReadOnlyList`1) + 0x42e
at Microsoft.AspNetCore.Routing.RouteEndpointDataSource.GetGroupedEndpoints(RouteGroupContext) + 0xb4
at Microsoft.AspNetCore.Routing.RouteGroupBuilder.GroupEndpointDataSource.GetGroupedEndpointsWithNullablePrefix(RoutePattern, IReadOnlyList`1, IReadOnlyList`1, IServiceProvider) + 0x58
at Microsoft.AspNetCore.Routing.RouteGroupBuilder.GroupEndpointDataSource.get_Endpoints() + 0x3f
at Microsoft.AspNetCore.Routing.CompositeEndpointDataSource.CreateEndpointsUnsynchronized() + 0x6c
at Microsoft.AspNetCore.Routing.CompositeEndpointDataSource.EnsureEndpointsInitialized() + 0x4c
at Microsoft.AspNetCore.Routing.CompositeEndpointDataSource.get_Endpoints() + 0x10
at Microsoft.AspNetCore.Routing.DataSourceDependentCache`1.Initialize() + 0x44
at System.Threading.LazyInitializer.EnsureInitializedCore[T](T&, Boolean&, Object&, Func`1) + 0x43
at Microsoft.AspNetCore.Routing.Matching.DataSourceDependentMatcher..ctor(EndpointDataSource, DataSourceDependentMatcher.Lifetime, Func`1) + 0x96
at Microsoft.AspNetCore.Routing.Matching.DfaMatcherFactory.CreateMatcher(EndpointDataSource) + 0x61
at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.InitializeCoreAsync() + 0x8a
--- End of stack trace from previous location ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x20
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task) + 0xb2
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task) + 0x42
at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.<<Invoke>g__AwaitMatcher|9_0>d.MoveNext() + 0xc1
--- End of stack trace from previous location ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x20
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task) + 0xb2
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.<ProcessRequests>d__238`1.MoveNext() + 0x460
This is due to MapShortCircuit using a compiler generated delegate as the RequestDelegate and native AOT not supporting getting MethodInfo on compiler generated delegates (see dotnet/runtime#85042):
aspnetcore/src/Http/Routing/src/ShortCircuit/RouteShortCircuitEndpointRouteBuilderExtensions.cs
Line 14 in 1b78513
| private static readonly RequestDelegate _shortCircuitDelegate = (context) => Task.CompletedTask; |
Repro
- Create an ASP.NET Core project using the "API' project template and enabled for native AOT publish:
dotnet new api --aot - Add a call to
app.MapShortCircuit(StatusCodes.Status404NotFound, "/favicon.ico"), e.g.:using System.Text.Json.Serialization; using ShortCircuitNativeAot; var builder = WebApplication.CreateSlimBuilder(args); builder.Logging.AddConsole(); builder.Services.ConfigureHttpJsonOptions(options => { options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default); }); var app = builder.Build(); app.MapShortCircuit(StatusCodes.Status404NotFound, "/favicon.ico"); var sampleTodos = TodoGenerator.GenerateTodos().ToArray(); var todosApi = app.MapGroup("/todos"); todosApi.MapGet("/", () => sampleTodos); todosApi.MapGet("/{id}", (int id) => sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo ? Results.Ok(todo) : Results.NotFound()); app.Run(); [JsonSerializable(typeof(Todo[]))] internal partial class AppJsonSerializerContext : JsonSerializerContext { }
- Publish the project:
dotnet publish - Run the published app, e.g.:
.\bin\Release\net8.0\win-x64\publish\ShortCircuitNativeAot.exe - Make a request to the app on
http://localhost:5000
Metadata
Metadata
Assignees
Labels
NativeAOTfeature-routingneeds-area-labelUsed by the dotnet-issue-labeler to label those issues which couldn't be triaged automaticallyUsed by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically