Created
August 14, 2018 18:45
-
-
Save matheusneder/bb5a023d11686ad35f7b8344d8a7362e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class OtcApiVersionActionSelector : ApiVersionActionSelector | |
{ | |
public OtcApiVersionActionSelector(IActionDescriptorCollectionProvider actionDescriptorCollectionProvider, ActionConstraintCache actionConstraintCache, IOptions<ApiVersioningOptions> options, ILoggerFactory loggerFactory, IApiVersionRoutePolicy routePolicy) : base(actionDescriptorCollectionProvider, actionConstraintCache, options, loggerFactory, routePolicy) | |
{ | |
} | |
public override ActionDescriptor SelectBestCandidate(RouteContext context, IReadOnlyList<ActionDescriptor> candidates) | |
{ | |
if (context == null) | |
{ | |
throw new ArgumentNullException(nameof(context)); | |
} | |
if (candidates == null) | |
{ | |
throw new ArgumentNullException(nameof(candidates)); | |
} | |
var httpContext = context.HttpContext; | |
if (IsRequestedApiVersionAmbiguous(context, out var apiVersion)) | |
{ | |
return null; | |
} | |
var matches = EvaluateActionConstraints(context, candidates); | |
var selectedAction = SelectActionWithoutApiVersionConvention(matches); | |
// this block "if" is a custom implementation from Ole Consignado | |
// its purpose is to select the version from url route, | |
// it will select the upperest version after applying ApiVersion <= ApiVersionInUrl filter from canditades | |
// Example: | |
// The api has a GET method on XptosController for ApiVersion("1.0"), ApiVersion("1.5") and ApiVersion("2.0") | |
// If receives a request: | |
// GET /v1.8/xptos | |
// It will be routed to ApiVersion("1.5") | |
if (selectedAction == null) | |
{ | |
// Transform candidate (List of ActionDescriptor) list to a list of new { ActionDescriptor, ApiVersion } | |
// in order to make filtering easier | |
var transformedCandidates = matches.Select(m => new | |
{ | |
Candidates = m.Properties.Where( | |
p => p.Key is Type && typeof(ApiVersionModel).IsAssignableFrom(p.Key as Type)) | |
.Select(t => (t.Value as ApiVersionModel).DeclaredApiVersions) | |
.Single() | |
.Select(a => | |
new | |
{ | |
ApiVersion = a, | |
ActionDescriptor = m | |
}) | |
.ToList() | |
}).SelectMany(c => c.Candidates).ToList(); | |
selectedAction = transformedCandidates | |
.Where(t => t.ApiVersion <= apiVersion /* the given apiVersion in url (from RouteContext) */ ) | |
.OrderByDescending(t => t.ApiVersion) | |
.FirstOrDefault()?.ActionDescriptor; | |
} | |
if (selectedAction != null) | |
{ | |
return selectedAction; | |
} | |
var selectionContext = new ActionSelectionContext(httpContext, matches, apiVersion); | |
var finalMatches = SelectBestActions(selectionContext); | |
var feature = httpContext.Features.Get<IApiVersioningFeature>(); | |
var selectionResult = feature.SelectionResult; | |
feature.RequestedApiVersion = selectionContext.RequestedVersion; | |
selectionResult.AddCandidates(candidates); | |
if (finalMatches.Count == 0) | |
{ | |
return null; | |
} | |
selectionResult.AddMatches(finalMatches); | |
return RoutePolicy.Evaluate(context, selectionResult); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment