@@ -62,9 +62,7 @@ public static partial class RequestDelegateFactory
62
62
private static readonly PropertyInfo HeaderIndexerProperty = typeof ( IHeaderDictionary ) . GetProperty ( "Item" ) ! ;
63
63
private static readonly PropertyInfo FormFilesIndexerProperty = typeof ( IFormFileCollection ) . GetProperty ( "Item" ) ! ;
64
64
65
- // Call WriteAsJsonAsync<object?>() to serialize the runtime return type rather than the declared return type.
66
- // https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-polymorphism
67
- private static readonly MethodInfo JsonResultWriteResponseAsyncMethod = GetMethodInfo < Func < HttpResponse , object ? , Task > > ( ( response , value ) => HttpResponseJsonExtensions . WriteAsJsonAsync < object ? > ( response , value , default ) ) ;
65
+ private static readonly MethodInfo JsonResultWriteResponseAsyncMethod = typeof ( RequestDelegateFactory ) . GetMethod ( nameof ( WriteJsonResponse ) , BindingFlags . NonPublic | BindingFlags . Static ) ! ;
68
66
69
67
private static readonly MethodInfo LogParameterBindingFailedMethod = GetMethodInfo < Action < HttpContext , string , string , string , bool > > ( ( httpContext , parameterType , parameterName , sourceValue , shouldThrow ) =>
70
68
Log . ParameterBindingFailed ( httpContext , parameterType , parameterName , sourceValue , shouldThrow ) ) ;
@@ -1086,11 +1084,11 @@ private static Expression AddResponseWritingToMethodCall(Expression methodCall,
1086
1084
else if ( returnType . IsValueType )
1087
1085
{
1088
1086
var box = Expression . TypeAs ( methodCall , typeof ( object ) ) ;
1089
- return Expression . Call ( JsonResultWriteResponseAsyncMethod , HttpResponseExpr , box , Expression . Constant ( CancellationToken . None ) ) ;
1087
+ return Expression . Call ( JsonResultWriteResponseAsyncMethod , HttpResponseExpr , box ) ;
1090
1088
}
1091
1089
else
1092
1090
{
1093
- return Expression . Call ( JsonResultWriteResponseAsyncMethod , HttpResponseExpr , methodCall , Expression . Constant ( CancellationToken . None ) ) ;
1091
+ return Expression . Call ( JsonResultWriteResponseAsyncMethod , HttpResponseExpr , methodCall ) ;
1094
1092
}
1095
1093
}
1096
1094
@@ -2036,8 +2034,7 @@ private static Task ExecuteAwaitedReturn(object obj, HttpContext httpContext)
2036
2034
else
2037
2035
{
2038
2036
// Otherwise, we JSON serialize when we reach the terminal state
2039
- // Call WriteAsJsonAsync<object?>() to serialize the runtime return type rather than the declared return type.
2040
- return httpContext . Response . WriteAsJsonAsync < object ? > ( obj ) ;
2037
+ return WriteJsonResponse ( httpContext . Response , obj ) ;
2041
2038
}
2042
2039
}
2043
2040
@@ -2047,14 +2044,12 @@ private static Task ExecuteTaskOfT<T>(Task<T> task, HttpContext httpContext)
2047
2044
2048
2045
static async Task ExecuteAwaited ( Task < T > task , HttpContext httpContext )
2049
2046
{
2050
- // Call WriteAsJsonAsync<object?>() to serialize the runtime return type rather than the declared return type.
2051
- await httpContext . Response . WriteAsJsonAsync < object ? > ( await task ) ;
2047
+ await WriteJsonResponse ( httpContext . Response , await task ) ;
2052
2048
}
2053
2049
2054
2050
if ( task . IsCompletedSuccessfully )
2055
2051
{
2056
- // Call WriteAsJsonAsync<object?>() to serialize the runtime return type rather than the declared return type.
2057
- return httpContext . Response . WriteAsJsonAsync < object ? > ( task . GetAwaiter ( ) . GetResult ( ) ) ;
2052
+ return WriteJsonResponse ( httpContext . Response , task . GetAwaiter ( ) . GetResult ( ) ) ;
2058
2053
}
2059
2054
2060
2055
return ExecuteAwaited ( task , httpContext ) ;
@@ -2137,14 +2132,12 @@ private static Task ExecuteValueTaskOfT<T>(ValueTask<T> task, HttpContext httpCo
2137
2132
{
2138
2133
static async Task ExecuteAwaited ( ValueTask < T > task , HttpContext httpContext )
2139
2134
{
2140
- // Call WriteAsJsonAsync<object?>() to serialize the runtime return type rather than the declared return type.
2141
- await httpContext . Response . WriteAsJsonAsync < object ? > ( await task ) ;
2135
+ await WriteJsonResponse ( httpContext . Response , await task ) ;
2142
2136
}
2143
2137
2144
2138
if ( task . IsCompletedSuccessfully )
2145
2139
{
2146
- // Call WriteAsJsonAsync<object?>() to serialize the runtime return type rather than the declared return type.
2147
- return httpContext . Response . WriteAsJsonAsync < object ? > ( task . GetAwaiter ( ) . GetResult ( ) ) ;
2140
+ return WriteJsonResponse ( httpContext . Response , task . GetAwaiter ( ) . GetResult ( ) ) ;
2148
2141
}
2149
2142
2150
2143
return ExecuteAwaited ( task , httpContext ) ;
@@ -2194,6 +2187,16 @@ private static async Task ExecuteResultWriteResponse(IResult? result, HttpContex
2194
2187
await EnsureRequestResultNotNull ( result ) . ExecuteAsync ( httpContext ) ;
2195
2188
}
2196
2189
2190
+ private static Task WriteJsonResponse ( HttpResponse response , object ? value )
2191
+ {
2192
+ // Call WriteAsJsonAsync() with the runtime type to serialize the runtime type rather than the declared type
2193
+ // and avoid source generators issues.
2194
+ // https://github.com/dotnet/aspnetcore/issues/43894
2195
+ // https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-polymorphism
2196
+ return HttpResponseJsonExtensions . WriteAsJsonAsync ( response , value , value is null ? typeof ( object ) : value . GetType ( ) , default ) ;
2197
+
2198
+ }
2199
+
2197
2200
private static NotSupportedException GetUnsupportedReturnTypeException ( Type returnType )
2198
2201
{
2199
2202
return new NotSupportedException ( $ "Unsupported return type: { TypeNameHelper . GetTypeDisplayName ( returnType ) } ") ;
0 commit comments