@@ -55,8 +55,6 @@ public FilterActionInvoker(
55
55
_modelValidatorProviderProvider = modelValidatorProviderProvider ;
56
56
_valueProviderFactoryProvider = valueProviderFactoryProvider ;
57
57
_actionBindingContextAccessor = actionBindingContextAccessor ;
58
-
59
- ActionBindingContext = new ActionBindingContext ( ) ;
60
58
}
61
59
62
60
protected ActionContext ActionContext { get ; private set ; }
@@ -73,6 +71,21 @@ private set
73
71
}
74
72
}
75
73
74
+ protected object Instance { get ; private set ; }
75
+
76
+ /// <summary>
77
+ /// Called to create an instance of an object which will act as the reciever of the action invocation.
78
+ /// </summary>
79
+ /// <returns>The constructed instance or <c>null</c>.</returns>
80
+ protected abstract object CreateInstance ( ) ;
81
+
82
+ /// <summary>
83
+ /// Called to create an instance of an object which will act as the reciever of the action invocation.
84
+ /// </summary>
85
+ /// <param name="instance">The instance to release.</param>
86
+ /// <remarks>This method will not be called if <see cref="CreateInstance"/> returns <c>null</c>.</remarks>
87
+ protected abstract void ReleaseInstance ( object instance ) ;
88
+
76
89
protected abstract Task < IActionResult > InvokeActionAsync ( ActionExecutingContext actionExecutingContext ) ;
77
90
78
91
protected abstract Task < IDictionary < string , object > > GetActionArgumentsAsync (
@@ -95,7 +108,20 @@ public virtual async Task InvokeAsync()
95
108
return ;
96
109
}
97
110
98
- await InvokeAllResourceFiltersAsync ( ) ;
111
+ try
112
+ {
113
+ await InvokeAllResourceFiltersAsync ( ) ;
114
+ }
115
+ finally
116
+ {
117
+ // Release the instance after all filters have run. We don't need to surround
118
+ // Authorizations filters because the instance will be created much later than
119
+ // that.
120
+ if ( Instance != null )
121
+ {
122
+ ReleaseInstance ( Instance ) ;
123
+ }
124
+ }
99
125
100
126
// We've reached the end of resource filters. If there's an unhandled exception on the context then
101
127
// it should be thrown and middleware has a chance to handle it.
@@ -207,7 +233,7 @@ private async Task<ResourceExecutedContext> InvokeResourceFilterAsync()
207
233
if ( item . FilterAsync != null )
208
234
{
209
235
await item . FilterAsync . OnResourceExecutionAsync (
210
- _resourceExecutingContext ,
236
+ _resourceExecutingContext ,
211
237
InvokeResourceFilterAsync ) ;
212
238
213
239
if ( _resourceExecutedContext == null )
@@ -384,23 +410,30 @@ private async Task InvokeAllActionFiltersAsync()
384
410
385
411
Debug . Assert ( _resourceExecutingContext != null ) ;
386
412
387
- Debug . Assert ( ActionBindingContext != null ) ;
413
+ ActionBindingContext = new ActionBindingContext ( ) ;
388
414
ActionBindingContext . InputFormatters = _resourceExecutingContext . InputFormatters ;
389
415
ActionBindingContext . ModelBinder = new CompositeModelBinder ( _resourceExecutingContext . ModelBinders ) ;
390
416
ActionBindingContext . ValidatorProvider = new CompositeModelValidatorProvider (
391
417
_resourceExecutingContext . ValidatorProviders ) ;
392
418
393
419
var valueProviderFactoryContext = new ValueProviderFactoryContext (
394
- ActionContext . HttpContext ,
420
+ ActionContext . HttpContext ,
395
421
ActionContext . RouteData . Values ) ;
396
422
397
423
ActionBindingContext . ValueProvider = CompositeValueProvider . Create (
398
424
_resourceExecutingContext . ValueProviderFactories ,
399
425
valueProviderFactoryContext ) ;
400
426
427
+ Instance = CreateInstance ( ) ;
428
+
401
429
var arguments = await GetActionArgumentsAsync ( ActionContext , ActionBindingContext ) ;
402
430
403
- _actionExecutingContext = new ActionExecutingContext ( ActionContext , _filters , arguments ) ;
431
+ _actionExecutingContext = new ActionExecutingContext (
432
+ ActionContext ,
433
+ _filters ,
434
+ arguments ,
435
+ Instance ) ;
436
+
404
437
await InvokeActionFilterAsync ( ) ;
405
438
}
406
439
@@ -429,7 +462,10 @@ private async Task<ActionExecutedContext> InvokeActionFilterAsync()
429
462
if ( _actionExecutedContext == null )
430
463
{
431
464
// If we get here then the filter didn't call 'next' indicating a short circuit
432
- _actionExecutedContext = new ActionExecutedContext ( _actionExecutingContext , _filters )
465
+ _actionExecutedContext = new ActionExecutedContext (
466
+ _actionExecutingContext ,
467
+ _filters ,
468
+ Instance )
433
469
{
434
470
Canceled = true ,
435
471
Result = _actionExecutingContext . Result ,
@@ -443,7 +479,10 @@ private async Task<ActionExecutedContext> InvokeActionFilterAsync()
443
479
if ( _actionExecutingContext . Result != null )
444
480
{
445
481
// Short-circuited by setting a result.
446
- _actionExecutedContext = new ActionExecutedContext ( _actionExecutingContext , _filters )
482
+ _actionExecutedContext = new ActionExecutedContext (
483
+ _actionExecutingContext ,
484
+ _filters ,
485
+ Instance )
447
486
{
448
487
Canceled = true ,
449
488
Result = _actionExecutingContext . Result ,
@@ -457,7 +496,10 @@ private async Task<ActionExecutedContext> InvokeActionFilterAsync()
457
496
else
458
497
{
459
498
// All action filters have run, execute the action method.
460
- _actionExecutedContext = new ActionExecutedContext ( _actionExecutingContext , _filters )
499
+ _actionExecutedContext = new ActionExecutedContext (
500
+ _actionExecutingContext ,
501
+ _filters ,
502
+ Instance )
461
503
{
462
504
Result = await InvokeActionAsync ( _actionExecutingContext ) ,
463
505
} ;
@@ -466,7 +508,10 @@ private async Task<ActionExecutedContext> InvokeActionFilterAsync()
466
508
catch ( Exception exception )
467
509
{
468
510
// Exceptions thrown by the action method OR filters bubble back up through ActionExcecutedContext.
469
- _actionExecutedContext = new ActionExecutedContext ( _actionExecutingContext , _filters )
511
+ _actionExecutedContext = new ActionExecutedContext (
512
+ _actionExecutingContext ,
513
+ _filters ,
514
+ Instance )
470
515
{
471
516
ExceptionDispatchInfo = ExceptionDispatchInfo . Capture ( exception )
472
517
} ;
@@ -478,7 +523,7 @@ private async Task InvokeAllResultFiltersAsync(IActionResult result)
478
523
{
479
524
_cursor . SetStage ( FilterStage . ResultFilters ) ;
480
525
481
- _resultExecutingContext = new ResultExecutingContext ( ActionContext , _filters , result ) ;
526
+ _resultExecutingContext = new ResultExecutingContext ( ActionContext , _filters , result , Instance ) ;
482
527
await InvokeResultFilterAsync ( ) ;
483
528
484
529
Debug . Assert ( _resultExecutingContext != null ) ;
@@ -525,7 +570,8 @@ private async Task<ResultExecutedContext> InvokeResultFilterAsync()
525
570
_resultExecutedContext = new ResultExecutedContext (
526
571
_resultExecutingContext ,
527
572
_filters ,
528
- _resultExecutingContext . Result )
573
+ _resultExecutingContext . Result ,
574
+ Instance )
529
575
{
530
576
Canceled = true ,
531
577
} ;
@@ -536,7 +582,8 @@ private async Task<ResultExecutedContext> InvokeResultFilterAsync()
536
582
_resultExecutedContext = new ResultExecutedContext (
537
583
_resultExecutingContext ,
538
584
_filters ,
539
- _resultExecutingContext . Result )
585
+ _resultExecutingContext . Result ,
586
+ Instance )
540
587
{
541
588
Canceled = true ,
542
589
} ;
@@ -552,7 +599,8 @@ private async Task<ResultExecutedContext> InvokeResultFilterAsync()
552
599
_resultExecutedContext = new ResultExecutedContext (
553
600
_resultExecutingContext ,
554
601
_filters ,
555
- _resultExecutingContext . Result )
602
+ _resultExecutingContext . Result ,
603
+ Instance )
556
604
{
557
605
Canceled = true ,
558
606
} ;
@@ -570,15 +618,17 @@ private async Task<ResultExecutedContext> InvokeResultFilterAsync()
570
618
_resultExecutedContext = new ResultExecutedContext (
571
619
_resultExecutingContext ,
572
620
_filters ,
573
- _resultExecutingContext . Result ) ;
621
+ _resultExecutingContext . Result ,
622
+ Instance ) ;
574
623
}
575
624
}
576
625
catch ( Exception exception )
577
626
{
578
627
_resultExecutedContext = new ResultExecutedContext (
579
628
_resultExecutingContext ,
580
629
_filters ,
581
- _resultExecutingContext . Result )
630
+ _resultExecutingContext . Result ,
631
+ Instance )
582
632
{
583
633
ExceptionDispatchInfo = ExceptionDispatchInfo . Capture ( exception )
584
634
} ;
0 commit comments