88using System . Reflection ;
99using System . Security . Claims ;
1010using System . Text ;
11+ using System . Text . Json ;
1112using Microsoft . AspNetCore . Http . Features ;
1213using Microsoft . AspNetCore . Http . Metadata ;
1314using Microsoft . Extensions . DependencyInjection ;
@@ -504,7 +505,7 @@ private static Expression AddResponseWritingToMethodCall(Expression methodCall,
504505
505506 private static Func < object ? , HttpContext , Task > HandleRequestBodyAndCompileRequestDelegate ( Expression responseWritingMethodCall , FactoryContext factoryContext )
506507 {
507- if ( factoryContext . JsonRequestBodyType is null )
508+ if ( factoryContext . JsonRequestBodyParameter is null )
508509 {
509510 if ( factoryContext . ParameterBinders . Count > 0 )
510511 {
@@ -533,7 +534,12 @@ private static Expression AddResponseWritingToMethodCall(Expression methodCall,
533534 responseWritingMethodCall , TargetExpr , HttpContextExpr ) . Compile ( ) ;
534535 }
535536
536- var bodyType = factoryContext . JsonRequestBodyType ;
537+ var bodyType = factoryContext . JsonRequestBodyParameter . ParameterType ;
538+ var parameterTypeName = TypeNameHelper . GetTypeDisplayName ( factoryContext . JsonRequestBodyParameter . ParameterType , fullName : false ) ;
539+ var parameterName = factoryContext . JsonRequestBodyParameter . Name ;
540+
541+ Debug . Assert ( parameterName is not null , "CreateArgument() should throw if parameter.Name is null." ) ;
542+
537543 object ? defaultBodyValue = null ;
538544
539545 if ( factoryContext . AllowEmptyRequestBody && bodyType . IsValueType )
@@ -580,10 +586,10 @@ private static Expression AddResponseWritingToMethodCall(Expression methodCall,
580586 Log . RequestBodyIOException ( httpContext , ex ) ;
581587 return ;
582588 }
583- catch ( InvalidDataException ex )
589+ catch ( JsonException ex )
584590 {
585- Log . RequestBodyInvalidDataException ( httpContext , ex , factoryContext . ThrowOnBadRequest ) ;
586- httpContext . Response . StatusCode = 400 ;
591+ Log . InvalidJsonRequestBody ( httpContext , parameterTypeName , parameterName , ex , factoryContext . ThrowOnBadRequest ) ;
592+ httpContext . Response . StatusCode = StatusCodes . Status400BadRequest ;
587593 return ;
588594 }
589595 }
@@ -618,10 +624,10 @@ private static Expression AddResponseWritingToMethodCall(Expression methodCall,
618624 Log . RequestBodyIOException ( httpContext , ex ) ;
619625 return ;
620626 }
621- catch ( InvalidDataException ex )
627+ catch ( JsonException ex )
622628 {
623629
624- Log . RequestBodyInvalidDataException ( httpContext , ex , factoryContext . ThrowOnBadRequest ) ;
630+ Log . InvalidJsonRequestBody ( httpContext , parameterTypeName , parameterName , ex , factoryContext . ThrowOnBadRequest ) ;
625631 httpContext . Response . StatusCode = StatusCodes . Status400BadRequest ;
626632 return ;
627633 }
@@ -879,11 +885,14 @@ private static Expression BindParameterFromBindAsync(ParameterInfo parameter, Fa
879885
880886 private static Expression BindParameterFromBody ( ParameterInfo parameter , bool allowEmpty , FactoryContext factoryContext )
881887 {
882- if ( factoryContext . JsonRequestBodyType is not null )
888+ if ( factoryContext . JsonRequestBodyParameter is not null )
883889 {
884890 factoryContext . HasMultipleBodyParameters = true ;
885891 var parameterName = parameter . Name ;
886- if ( parameterName is not null && factoryContext . TrackedParameters . ContainsKey ( parameterName ) )
892+
893+ Debug . Assert ( parameterName is not null , "CreateArgument() should throw if parameter.Name is null." ) ;
894+
895+ if ( factoryContext . TrackedParameters . ContainsKey ( parameterName ) )
887896 {
888897 factoryContext . TrackedParameters . Remove ( parameterName ) ;
889898 factoryContext . TrackedParameters . Add ( parameterName , "UNKNOWN" ) ;
@@ -892,7 +901,7 @@ private static Expression BindParameterFromBody(ParameterInfo parameter, bool al
892901
893902 var isOptional = IsOptionalParameter ( parameter , factoryContext ) ;
894903
895- factoryContext . JsonRequestBodyType = parameter . ParameterType ;
904+ factoryContext . JsonRequestBodyParameter = parameter ;
896905 factoryContext . AllowEmptyRequestBody = allowEmpty || isOptional ;
897906 factoryContext . Metadata . Add ( new AcceptsMetadata ( parameter . ParameterType , factoryContext . AllowEmptyRequestBody , DefaultAcceptsContentType ) ) ;
898907
@@ -1164,7 +1173,7 @@ private class FactoryContext
11641173 public bool DisableInferredFromBody { get ; init ; }
11651174
11661175 // Temporary State
1167- public Type ? JsonRequestBodyType { get ; set ; }
1176+ public ParameterInfo ? JsonRequestBodyParameter { get ; set ; }
11681177 public bool AllowEmptyRequestBody { get ; set ; }
11691178
11701179 public bool UsingTempSourceString { get ; set ; }
@@ -1197,7 +1206,8 @@ private static class RequestDelegateFactoryConstants
11971206
11981207 private static partial class Log
11991208 {
1200- private const string RequestBodyInvalidDataExceptionMessage = "Reading the request body failed with an InvalidDataException." ;
1209+ private const string InvalidJsonRequestBodyMessage = @"Failed to read parameter ""{ParameterType} {ParameterName}"" from the request body as JSON." ;
1210+ private const string InvalidJsonRequestBodyExceptionMessage = @"Failed to read parameter ""{0} {1}"" from the request body as JSON." ;
12011211
12021212 private const string ParameterBindingFailedLogMessage = @"Failed to bind parameter ""{ParameterType} {ParameterName}"" from ""{SourceValue}""." ;
12031213 private const string ParameterBindingFailedExceptionMessage = @"Failed to bind parameter ""{0} {1}"" from ""{2}""." ;
@@ -1207,6 +1217,7 @@ private static partial class Log
12071217
12081218 private const string UnexpectedContentTypeLogMessage = @"Expected a supported JSON media type but got ""{ContentType}""." ;
12091219 private const string UnexpectedContentTypeExceptionMessage = @"Expected a supported JSON media type but got ""{0}""." ;
1220+
12101221 private const string ImplicitBodyNotProvidedLogMessage = @"Implicit body inferred for parameter ""{ParameterName}"" but no body was provided. Did you mean to use a Service instead?" ;
12111222 private const string ImplicitBodyNotProvidedExceptionMessage = @"Implicit body inferred for parameter ""{0}"" but no body was provided. Did you mean to use a Service instead?" ;
12121223
@@ -1218,18 +1229,19 @@ public static void RequestBodyIOException(HttpContext httpContext, IOException e
12181229 [ LoggerMessage ( 1 , LogLevel . Debug , "Reading the request body failed with an IOException." , EventName = "RequestBodyIOException" ) ]
12191230 private static partial void RequestBodyIOException ( ILogger logger , IOException exception ) ;
12201231
1221- public static void RequestBodyInvalidDataException ( HttpContext httpContext , InvalidDataException exception , bool shouldThrow )
1232+ public static void InvalidJsonRequestBody ( HttpContext httpContext , string parameterTypeName , string parameterName , Exception exception , bool shouldThrow )
12221233 {
12231234 if ( shouldThrow )
12241235 {
1225- throw new BadHttpRequestException ( RequestBodyInvalidDataExceptionMessage , exception ) ;
1236+ var message = string . Format ( CultureInfo . InvariantCulture , InvalidJsonRequestBodyExceptionMessage , parameterTypeName , parameterName ) ;
1237+ throw new BadHttpRequestException ( message , exception ) ;
12261238 }
12271239
1228- RequestBodyInvalidDataException ( GetLogger ( httpContext ) , exception ) ;
1240+ InvalidJsonRequestBody ( GetLogger ( httpContext ) , parameterTypeName , parameterName , exception ) ;
12291241 }
12301242
1231- [ LoggerMessage ( 2 , LogLevel . Debug , RequestBodyInvalidDataExceptionMessage , EventName = "RequestBodyInvalidDataException " ) ]
1232- private static partial void RequestBodyInvalidDataException ( ILogger logger , InvalidDataException exception ) ;
1243+ [ LoggerMessage ( 2 , LogLevel . Debug , InvalidJsonRequestBodyMessage , EventName = "InvalidJsonRequestBody " ) ]
1244+ private static partial void InvalidJsonRequestBody ( ILogger logger , string parameterType , string parameterName , Exception exception ) ;
12331245
12341246 public static void ParameterBindingFailed ( HttpContext httpContext , string parameterTypeName , string parameterName , string sourceValue , bool shouldThrow )
12351247 {
@@ -1259,16 +1271,6 @@ public static void RequiredParameterNotProvided(HttpContext httpContext, string
12591271 [ LoggerMessage ( 4 , LogLevel . Debug , RequiredParameterNotProvidedLogMessage , EventName = "RequiredParameterNotProvided" ) ]
12601272 private static partial void RequiredParameterNotProvided ( ILogger logger , string parameterType , string parameterName , string source ) ;
12611273
1262- public static void UnexpectedContentType ( HttpContext httpContext , string ? contentType , bool shouldThrow )
1263- {
1264- if ( shouldThrow )
1265- {
1266- var message = string . Format ( CultureInfo . InvariantCulture , UnexpectedContentTypeExceptionMessage , contentType ) ;
1267- throw new BadHttpRequestException ( message , StatusCodes . Status415UnsupportedMediaType ) ;
1268- }
1269-
1270- UnexpectedContentType ( GetLogger ( httpContext ) , contentType ?? "(none)" ) ;
1271- }
12721274 public static void ImplicitBodyNotProvided ( HttpContext httpContext , string parameterName , bool shouldThrow )
12731275 {
12741276 if ( shouldThrow )
@@ -1283,8 +1285,16 @@ public static void ImplicitBodyNotProvided(HttpContext httpContext, string param
12831285 [ LoggerMessage ( 5 , LogLevel . Debug , ImplicitBodyNotProvidedLogMessage , EventName = "ImplicitBodyNotProvided" ) ]
12841286 private static partial void ImplicitBodyNotProvided ( ILogger logger , string parameterName ) ;
12851287
1286- public static void UnexpectedContentType ( HttpContext httpContext , string ? contentType )
1287- => UnexpectedContentType ( GetLogger ( httpContext ) , contentType ?? "(none)" ) ;
1288+ public static void UnexpectedContentType ( HttpContext httpContext , string ? contentType , bool shouldThrow )
1289+ {
1290+ if ( shouldThrow )
1291+ {
1292+ var message = string . Format ( CultureInfo . InvariantCulture , UnexpectedContentTypeExceptionMessage , contentType ) ;
1293+ throw new BadHttpRequestException ( message , StatusCodes . Status415UnsupportedMediaType ) ;
1294+ }
1295+
1296+ UnexpectedContentType ( GetLogger ( httpContext ) , contentType ?? "(none)" ) ;
1297+ }
12881298
12891299 [ LoggerMessage ( 6 , LogLevel . Debug , UnexpectedContentTypeLogMessage , EventName = "UnexpectedContentType" ) ]
12901300 private static partial void UnexpectedContentType ( ILogger logger , string contentType ) ;
0 commit comments