44using System . Threading . Tasks ;
55using System . Web . Http . Controllers ;
66using System . Web . Http . Metadata ;
7+ using System . Web . Http . Validation ;
78using System . Web . Http . ValueProviders ;
89using System . Web . Http . ValueProviders . Providers ;
910
@@ -17,6 +18,10 @@ public class ModelBinderParameterBinding : HttpParameterBinding
1718 private readonly IEnumerable < ValueProviderFactory > _valueProviderFactories ;
1819 private readonly ModelBinderProvider _modelBinderProvider ;
1920
21+ // Cache information for ModelBindingContext.
22+ private ModelMetadata _metadataCache ;
23+ private ModelValidationNode _validationNodeCache ;
24+
2025 public ModelBinderParameterBinding ( HttpParameterDescriptor descriptor ,
2126 ModelBinderProvider modelBinderProvider ,
2227 IEnumerable < ValueProviderFactory > valueProviderFactories )
@@ -46,6 +51,21 @@ public ModelBinderProvider ModelBinderProvider
4651 }
4752
4853 public override Task ExecuteBindingAsync ( ModelMetadataProvider metadataProvider , HttpActionContext actionContext , CancellationToken cancellationToken )
54+ {
55+ string name = Descriptor . ParameterName ;
56+
57+ ModelBindingContext ctx = GetModelBindingContext ( metadataProvider , actionContext ) ;
58+
59+ IModelBinder binder = this . _modelBinderProvider . GetBinder ( actionContext , ctx ) ;
60+
61+ bool haveResult = binder . BindModel ( actionContext , ctx ) ;
62+ object model = haveResult ? ctx . Model : Descriptor . DefaultValue ;
63+ actionContext . ActionArguments . Add ( name , model ) ;
64+
65+ return TaskHelpers . Completed ( ) ;
66+ }
67+
68+ private ModelBindingContext GetModelBindingContext ( ModelMetadataProvider metadataProvider , HttpActionContext actionContext )
4969 {
5070 string name = Descriptor . ParameterName ;
5171 Type type = Descriptor . ParameterType ;
@@ -54,22 +74,30 @@ public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider,
5474
5575 IValueProvider vp = CreateValueProvider ( this . _valueProviderFactories , actionContext ) ;
5676
77+ if ( _metadataCache == null )
78+ {
79+ Interlocked . Exchange ( ref _metadataCache , metadataProvider . GetMetadataForType ( null , type ) ) ;
80+ }
81+
5782 ModelBindingContext ctx = new ModelBindingContext ( )
5883 {
5984 ModelName = prefix ?? name ,
6085 FallbackToEmptyPrefix = prefix == null , // only fall back if prefix not specified
61- ModelMetadata = metadataProvider . GetMetadataForType ( null , type ) ,
86+ ModelMetadata = _metadataCache ,
6287 ModelState = actionContext . ModelState ,
6388 ValueProvider = vp
6489 } ;
90+
91+ if ( _validationNodeCache == null )
92+ {
93+ Interlocked . Exchange ( ref _validationNodeCache , ctx . ValidationNode ) ;
94+ }
95+ else
96+ {
97+ ctx . ValidationNode = _validationNodeCache ;
98+ }
6599
66- IModelBinder binder = this . _modelBinderProvider . GetBinder ( actionContext , ctx ) ;
67-
68- bool haveResult = binder . BindModel ( actionContext , ctx ) ;
69- object model = haveResult ? ctx . Model : Descriptor . DefaultValue ;
70- actionContext . ActionArguments . Add ( name , model ) ;
71-
72- return TaskHelpers . Completed ( ) ;
100+ return ctx ;
73101 }
74102
75103 // Instantiate the value providers for the given action context.
0 commit comments