@@ -23,6 +23,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
2323 /// </summary>
2424 public class NewtonsoftJsonInputFormatter : TextInputFormatter , IInputFormatterExceptionPolicy
2525 {
26+ internal const string EnableSkipHandledError = "Microsoft.AspNetCore.Mvc.NewtonsoftJson.EnableSkipHandledError" ;
27+
2628 private readonly IArrayPool < char > _charPool ;
2729 private readonly ILogger _logger ;
2830 private readonly ObjectPoolProvider _objectPoolProvider ;
@@ -79,6 +81,8 @@ public NewtonsoftJsonInputFormatter(
7981 _options = options ;
8082 _jsonOptions = jsonOptions ;
8183
84+ SkipHandledErrorEnabled = AppContext . TryGetSwitch ( EnableSkipHandledError , out var enabled ) && enabled ;
85+
8286 SupportedEncodings . Add ( UTF8EncodingWithoutBOM ) ;
8387 SupportedEncodings . Add ( UTF16EncodingLittleEndian ) ;
8488
@@ -109,6 +113,9 @@ public virtual InputFormatterExceptionPolicy ExceptionPolicy
109113 /// </remarks>
110114 protected JsonSerializerSettings SerializerSettings { get ; }
111115
116+ // internal for testing
117+ internal bool SkipHandledErrorEnabled { get ; set ; }
118+
112119 /// <inheritdoc />
113120 public override async Task < InputFormatterResult > ReadRequestBodyAsync (
114121 InputFormatterContext context ,
@@ -232,6 +239,13 @@ public override async Task<InputFormatterResult> ReadRequestBodyAsync(
232239
233240 void ErrorHandler ( object ? sender , Newtonsoft . Json . Serialization . ErrorEventArgs eventArgs )
234241 {
242+ // Skipping error, if it's already marked as handled
243+ // This allows user code to implement its own error handling
244+ if ( eventArgs . ErrorContext . Handled && SkipHandledErrorEnabled )
245+ {
246+ return ;
247+ }
248+
235249 successful = false ;
236250
237251 // When ErrorContext.Path does not include ErrorContext.Member, add Member to form full path.
0 commit comments