Skip to content

Commit 38bd06e

Browse files
Chris Martinezcommonsensesoftware
Chris Martinez
authored andcommitted
Updates action selection support for actions without API version models. Fixes #189.
1 parent 3f529d3 commit 38bd06e

File tree

1 file changed

+75
-27
lines changed

1 file changed

+75
-27
lines changed

src/Microsoft.AspNetCore.Mvc.Versioning/Versioning/ApiVersionActionSelector.cs

Lines changed: 75 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,13 @@ public virtual ActionDescriptor SelectBestCandidate( RouteContext context, IRead
142142
}
143143

144144
var matches = EvaluateActionConstraints( context, candidates );
145+
var selectedAction = SelectActionWithoutApiVersionConvention( matches );
146+
147+
if ( selectedAction != null )
148+
{
149+
return selectedAction;
150+
}
151+
145152
var selectionContext = new ActionSelectionContext( httpContext, matches, apiVersion );
146153
var finalMatches = SelectBestActions( selectionContext );
147154
var properties = httpContext.ApiVersionProperties();
@@ -150,34 +157,18 @@ public virtual ActionDescriptor SelectBestCandidate( RouteContext context, IRead
150157
properties.ApiVersion = selectionContext.RequestedVersion;
151158
selectionResult.AddCandidates( candidates );
152159

153-
if ( finalMatches == null )
160+
if ( finalMatches != null )
154161
{
155-
selectionResult.EndIteration();
156-
return null;
157-
}
158-
159-
if ( finalMatches.Count == 1 )
160-
{
161-
var selectedAction = finalMatches[0];
162-
163-
// note: short-circuit if the api version policy has already been applied to the match
164-
// and there are no other matches in a previous iteration which would take precendence
165-
if ( selectedAction.VersionPolicyIsApplied() && !selectionResult.HasMatchesInPreviousIterations )
162+
if ( ( selectedAction = SelectActionWithApiVersionPolicyApplied( finalMatches, selectionResult ) ) == null )
163+
{
164+
AppendPossibleMatches( finalMatches, context, selectionResult );
165+
}
166+
else
166167
{
167-
httpContext.ApiVersionProperties().ApiVersion = selectionContext.RequestedVersion;
168168
return selectedAction;
169169
}
170170
}
171171

172-
if ( finalMatches.Count > 0 )
173-
{
174-
var routeData = new RouteData( context.RouteData );
175-
var matchingActions = new MatchingActionSequence( finalMatches, routeData );
176-
177-
selectionResult.AddMatches( matchingActions );
178-
selectionResult.TrySetBestMatch( matchingActions.BestMatch );
179-
}
180-
181172
// note: even though we may have had a successful match, this method could be called multiple times. the final decision
182173
// is made by the IApiVersionRoutePolicy. we return here to make sure all candidates have been considered at least once.
183174
selectionResult.EndIteration();
@@ -238,6 +229,63 @@ where ActionIsSatisfiedBy( action, model, context.RequestedVersion, implicitMatc
238229
return bestMatches;
239230
}
240231

232+
ActionDescriptor SelectActionWithoutApiVersionConvention( IReadOnlyList<ActionDescriptor> matches )
233+
{
234+
Contract.Requires( matches != null );
235+
236+
if ( matches.Count != 1 )
237+
{
238+
return null;
239+
}
240+
241+
var selectedAction = matches[0];
242+
243+
if ( selectedAction.GetProperty<ApiVersionModel>() == null )
244+
{
245+
return selectedAction;
246+
}
247+
248+
return null;
249+
}
250+
251+
ActionDescriptor SelectActionWithApiVersionPolicyApplied( IReadOnlyList<ActionDescriptor> matches, ActionSelectionResult result )
252+
{
253+
Contract.Requires( matches != null );
254+
Contract.Requires( result != null );
255+
256+
if ( matches.Count != 1 )
257+
{
258+
return null;
259+
}
260+
261+
var match = matches[0];
262+
263+
if ( match.VersionPolicyIsApplied() && !result.HasMatchesInPreviousIterations )
264+
{
265+
return match;
266+
}
267+
268+
return null;
269+
}
270+
271+
void AppendPossibleMatches( IReadOnlyList<ActionDescriptor> matches, RouteContext context, ActionSelectionResult result )
272+
{
273+
Contract.Requires( matches != null );
274+
Contract.Requires( context != null );
275+
Contract.Requires( result != null );
276+
277+
if ( matches.Count == 0 )
278+
{
279+
return;
280+
}
281+
282+
var routeData = new RouteData( context.RouteData );
283+
var matchingActions = new MatchingActionSequence( matches, routeData );
284+
285+
result.AddMatches( matchingActions );
286+
result.TrySetBestMatch( matchingActions.BestMatch );
287+
}
288+
241289
RequestHandler VerifyRequestedApiVersionIsNotAmbiguous( HttpContext httpContext, out ApiVersion apiVersion )
242290
{
243291
Contract.Requires( httpContext != null );
@@ -474,8 +522,8 @@ public Cache( ActionDescriptorCollection actions )
474522
Contract.Requires( actions != null );
475523

476524
Version = actions.Version;
477-
OrdinalEntries = new Dictionary<string[], List<ActionDescriptor>>(StringArrayComparer.Ordinal);
478-
OrdinalIgnoreCaseEntries = new Dictionary<string[], List<ActionDescriptor>>(StringArrayComparer.OrdinalIgnoreCase);
525+
OrdinalEntries = new Dictionary<string[], List<ActionDescriptor>>( StringArrayComparer.Ordinal );
526+
OrdinalIgnoreCaseEntries = new Dictionary<string[], List<ActionDescriptor>>( StringArrayComparer.OrdinalIgnoreCase );
479527
RouteKeys = IdentifyRouteKeysForActionSelection( actions );
480528
BuildOrderedSetOfKeysForRouteValues( actions );
481529
}
@@ -500,7 +548,7 @@ static string[] IdentifyRouteKeysForActionSelection( ActionDescriptorCollection
500548
{
501549
foreach ( var kvp in action.RouteValues )
502550
{
503-
routeKeys.Add(kvp.Key);
551+
routeKeys.Add( kvp.Key );
504552
}
505553
}
506554
}
@@ -526,7 +574,7 @@ void BuildOrderedSetOfKeysForRouteValues( ActionDescriptorCollection actions )
526574
for ( var j = 0; j < RouteKeys.Length; j++ )
527575
{
528576

529-
action.RouteValues.TryGetValue(RouteKeys[j], out routeValues[j]);
577+
action.RouteValues.TryGetValue( RouteKeys[j], out routeValues[j] );
530578
}
531579

532580
if ( !OrdinalIgnoreCaseEntries.TryGetValue( routeValues, out var entries ) )
@@ -535,7 +583,7 @@ void BuildOrderedSetOfKeysForRouteValues( ActionDescriptorCollection actions )
535583
OrdinalIgnoreCaseEntries.Add( routeValues, entries );
536584
}
537585

538-
entries.Add(action);
586+
entries.Add( action );
539587

540588
if ( !OrdinalEntries.ContainsKey( routeValues ) )
541589
{

0 commit comments

Comments
 (0)