@@ -91,8 +91,17 @@ public static partial class RequestDelegateFactory
91
91
private static readonly MemberExpression FormFilesExpr = Expression . Property ( FormExpr , typeof ( IFormCollection ) . GetProperty ( nameof ( IFormCollection . Files ) ) ! ) ;
92
92
private static readonly MemberExpression StatusCodeExpr = Expression . Property ( HttpResponseExpr , typeof ( HttpResponse ) . GetProperty ( nameof ( HttpResponse . StatusCode ) ) ! ) ;
93
93
private static readonly MemberExpression CompletedTaskExpr = Expression . Property ( null , ( PropertyInfo ) GetMemberInfo < Func < Task > > ( ( ) => Task . CompletedTask ) ) ;
94
- private static readonly NewExpression EmptyHttpResultValueTaskExpr = Expression . New ( typeof ( ValueTask < object > ) . GetConstructor ( new [ ] { typeof ( EmptyHttpResult ) } ) ! , Expression . Property ( null , typeof ( EmptyHttpResult ) , nameof ( EmptyHttpResult . Instance ) ) ) ;
95
-
94
+ // Due to https://github.com/dotnet/aspnetcore/issues/41330 we cannot reference the EmptyHttpResult type
95
+ // but users still need to assert on it as in https://github.com/dotnet/aspnetcore/issues/45063
96
+ // so we temporarily work around this here by using reflection to get the actual type.
97
+ private static readonly object ? EmptyHttpResultInstance = Type . GetType ( "Microsoft.AspNetCore.Http.HttpResults.EmptyHttpResult, Microsoft.AspNetCore.Http.Results" ) ? . GetProperty ( "Instance" ) ? . GetValue ( null , null ) ;
98
+ #if DEBUG
99
+ private static readonly NewExpression EmptyHttpResultValueTaskExpr = EmptyHttpResultInstance is not null
100
+ ? Expression . New ( typeof ( ValueTask < object > ) . GetConstructor ( new [ ] { typeof ( IResult ) } ) ! , Expression . Constant ( EmptyHttpResultInstance ) )
101
+ : throw new UnreachableException ( "The EmptyHttpResult type could not be found." ) ;
102
+ #else
103
+ private static readonly NewExpression EmptyHttpResultValueTaskExpr = Expression . New ( typeof ( ValueTask < object > ) . GetConstructor ( new [ ] { typeof ( IResult ) } ) ! , Expression . Constant ( EmptyHttpResultInstance ) ) ;
104
+ #endif
96
105
private static readonly ParameterExpression TempSourceStringExpr = ParameterBindingMethodCache . TempSourceStringExpr ;
97
106
private static readonly BinaryExpression TempSourceStringNotNullExpr = Expression . NotEqual ( TempSourceStringExpr , Expression . Constant ( null ) ) ;
98
107
private static readonly BinaryExpression TempSourceStringNullExpr = Expression . Equal ( TempSourceStringExpr , Expression . Constant ( null ) ) ;
@@ -389,6 +398,7 @@ private static Expression[] CreateArgumentsAndInferMetadata(MethodInfo methodInf
389
398
private static EndpointFilterDelegate ? CreateFilterPipeline ( MethodInfo methodInfo , Expression ? targetExpression , RequestDelegateFactoryContext factoryContext , Expression < Func < HttpContext , object ? > > ? targetFactory )
390
399
{
391
400
Debug . Assert ( factoryContext . EndpointBuilder . FilterFactories . Count > 0 ) ;
401
+ Debug . Assert ( EmptyHttpResultInstance is not null , "The EmptyHttpResult type could not be found." ) ;
392
402
// httpContext.Response.StatusCode >= 400
393
403
// ? Task.CompletedTask
394
404
// : {
@@ -453,6 +463,7 @@ targetExpression is null
453
463
454
464
private static Expression MapHandlerReturnTypeToValueTask ( Expression methodCall , Type returnType )
455
465
{
466
+ Debug . Assert ( EmptyHttpResultInstance is not null , "The EmptyHttpResult type could not be found." ) ;
456
467
if ( returnType == typeof ( void ) )
457
468
{
458
469
return Expression . Block ( methodCall , EmptyHttpResultValueTaskExpr ) ;
@@ -2097,32 +2108,34 @@ static async Task ExecuteAwaited(ValueTask task)
2097
2108
2098
2109
private static ValueTask < object ? > ExecuteTaskWithEmptyResult ( Task task )
2099
2110
{
2111
+ Debug . Assert ( EmptyHttpResultInstance is not null , "The EmptyHttpResult type could not be found." ) ;
2100
2112
static async ValueTask < object ? > ExecuteAwaited ( Task task )
2101
2113
{
2102
2114
await task ;
2103
- return EmptyHttpResult . Instance ;
2115
+ return EmptyHttpResultInstance ;
2104
2116
}
2105
2117
2106
2118
if ( task . IsCompletedSuccessfully )
2107
2119
{
2108
- return new ValueTask < object ? > ( EmptyHttpResult . Instance ) ;
2120
+ return new ValueTask < object ? > ( EmptyHttpResultInstance ) ;
2109
2121
}
2110
2122
2111
2123
return ExecuteAwaited ( task ) ;
2112
2124
}
2113
2125
2114
2126
private static ValueTask < object ? > ExecuteValueTaskWithEmptyResult ( ValueTask valueTask )
2115
2127
{
2128
+ Debug . Assert ( EmptyHttpResultInstance is not null , "The EmptyHttpResult type could not be found." ) ;
2116
2129
static async ValueTask < object ? > ExecuteAwaited ( ValueTask task )
2117
2130
{
2118
2131
await task ;
2119
- return EmptyHttpResult . Instance ;
2132
+ return EmptyHttpResultInstance ;
2120
2133
}
2121
2134
2122
2135
if ( valueTask . IsCompletedSuccessfully )
2123
2136
{
2124
2137
valueTask . GetAwaiter ( ) . GetResult ( ) ;
2125
- return new ValueTask < object ? > ( EmptyHttpResult . Instance ) ;
2138
+ return new ValueTask < object ? > ( EmptyHttpResultInstance ) ;
2126
2139
}
2127
2140
2128
2141
return ExecuteAwaited ( valueTask ) ;
@@ -2442,24 +2455,6 @@ private static void FormatTrackedParameters(RequestDelegateFactoryContext factor
2442
2455
}
2443
2456
}
2444
2457
2445
- // Due to cyclic references between Http.Extensions and
2446
- // Http.Results, we define our own instance of the `EmptyHttpResult`
2447
- // type here.
2448
- private sealed class EmptyHttpResult : IResult
2449
- {
2450
- private EmptyHttpResult ( )
2451
- {
2452
- }
2453
-
2454
- public static EmptyHttpResult Instance { get ; } = new ( ) ;
2455
-
2456
- /// <inheritdoc/>
2457
- public Task ExecuteAsync ( HttpContext httpContext )
2458
- {
2459
- return Task . CompletedTask ;
2460
- }
2461
- }
2462
-
2463
2458
private sealed class RDFEndpointBuilder : EndpointBuilder
2464
2459
{
2465
2460
public RDFEndpointBuilder ( IServiceProvider applicationServices )
0 commit comments