Skip to content

Instantly share code, notes, and snippets.

@matheusneder
Created August 14, 2018 18:45
Show Gist options
  • Save matheusneder/bb5a023d11686ad35f7b8344d8a7362e to your computer and use it in GitHub Desktop.
Save matheusneder/bb5a023d11686ad35f7b8344d8a7362e to your computer and use it in GitHub Desktop.
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