internal override ControllerSelectionResult SelectController(ApiVersionControllerAggregator aggregator) { Contract.Requires(aggregator != null); Contract.Ensures(Contract.Result <ControllerSelectionResult>() != null); var request = aggregator.Request; var requestedVersion = aggregator.RequestedApiVersion; var controllerName = aggregator.ControllerName; var result = new ControllerSelectionResult() { RequestedVersion = requestedVersion, ControllerName = controllerName, HasCandidates = aggregator.HasConventionBasedRoutes }; if (!result.HasCandidates) { return(result); } var ambiguousException = new Lazy <Exception>(() => CreateAmbiguousControllerException(aggregator.RouteData.Route, controllerName, controllerTypeCache.GetControllerTypes(controllerName))); var versionNeutralController = result.Controller = GetVersionNeutralController(aggregator.ConventionRouteCandidates, ambiguousException); if (requestedVersion == null) { if (!AssumeDefaultVersionWhenUnspecified) { return(result); } requestedVersion = ApiVersionSelector.SelectVersion(request, aggregator.AllVersions); if (requestedVersion == null) { return(result); } } var versionedController = GetVersionedController(aggregator, requestedVersion, ambiguousException); if (versionedController == null) { return(result); } if (versionNeutralController != null) { throw ambiguousException.Value; } request.ApiVersionProperties().ApiVersion = requestedVersion; result.Controller = versionedController; return(result); }
internal override ControllerSelectionResult SelectController(ApiVersionControllerAggregator aggregator) { Contract.Requires(aggregator != null); Contract.Ensures(Contract.Result <ControllerSelectionResult>() != null); var request = aggregator.Request; var requestedVersion = aggregator.RequestedApiVersion; var result = new ControllerSelectionResult() { HasCandidates = aggregator.HasAttributeBasedRoutes, RequestedVersion = requestedVersion, }; if (!result.HasCandidates) { return(result); } var versionNeutralController = result.Controller = GetVersionNeutralController(aggregator.DirectRouteCandidates); if (requestedVersion == null) { if (!AssumeDefaultVersionWhenUnspecified) { return(result); } requestedVersion = ApiVersionSelector.SelectVersion(request, aggregator.AllVersions); if (requestedVersion == null) { return(result); } } var versionedController = GetVersionedController(aggregator, requestedVersion); if (versionedController == null) { return(result); } if (versionNeutralController != null) { throw CreateAmbiguousControllerException(new[] { versionNeutralController, versionedController }); } request.ApiVersionProperties().RequestedApiVersion = requestedVersion; result.RequestedVersion = requestedVersion; result.Controller = versionedController; return(result); }
/// <summary> /// Returns the set of best matching actions. /// </summary> /// <param name="context">The <see cref="ActionSelectionContext">context</see> to select the actions from.</param> /// <returns>A <see cref="IReadOnlyList{T}">read-only list</see> of the best matching <see cref="ActionDescriptor">actions</see>.</returns> protected virtual IReadOnlyList <ActionDescriptor> SelectBestActions(ActionSelectionContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var requestedVersion = context.RequestedVersion; if (requestedVersion == null) { if (Options.AssumeDefaultVersionWhenUnspecified) { context.RequestedVersion = requestedVersion = ApiVersionSelector.SelectVersion(context.HttpContext.Request, context.AllVersions); } } var bestMatches = new HashSet <ActionDescriptor>(); var implicitMatches = new HashSet <ActionDescriptor>(); for (var i = 0; i < context.MatchingActions.Count; i++) { var action = context.MatchingActions[i]; switch (action.MappingTo(requestedVersion)) { case Explicit: bestMatches.Add(action); break; case Implicit: implicitMatches.Add(action); break; } } if (bestMatches.Count == 0) { bestMatches.AddRange(implicitMatches); } if (bestMatches.Count == 1) { var model = bestMatches.Single().GetApiVersionModel(); if (model.IsApiVersionNeutral) { bestMatches.AddRange(implicitMatches); } } return(bestMatches.ToArray()); }
/// <summary> /// Returns the set of best matching actions. /// </summary> /// <param name="context">The <see cref="ActionSelectionContext">context</see> to select the actions from.</param> /// <returns>A <see cref="IReadOnlyList{T}">read-only list</see> of the best matching <see cref="ActionDescriptor">actions</see>.</returns> protected virtual IReadOnlyList <ActionDescriptor> SelectBestActions(ActionSelectionContext context) { Arg.NotNull(context, nameof(context)); Contract.Ensures(Contract.Result <IReadOnlyList <ActionDescriptor> >() != null); var bestMatches = new List <ActionDescriptor>(context.MatchingActions.Count); bestMatches.AddRange(MatchVersionNeutralActions(context)); if (context.RequestedVersion == null) { if (!Options.AssumeDefaultVersionWhenUnspecified) { return(bestMatches); } context.RequestedVersion = ApiVersionSelector.SelectVersion(context.HttpContext.Request, context.AllVersions); if (context.RequestedVersion == null) { return(bestMatches); } } var implicitMatches = new List <ActionDescriptor>(); var explicitMatches = from action in context.MatchingActions let model = action.GetProperty <ApiVersionModel>() where ActionIsSatisfiedBy(action, model, context.RequestedVersion, implicitMatches) select action; bestMatches.AddRange(explicitMatches); if (bestMatches.Count == 0) { bestMatches.AddRange(implicitMatches); } if (bestMatches.Count != 1) { return(bestMatches); } if (bestMatches[0].IsApiVersionNeutral()) { bestMatches.AddRange(implicitMatches); } return(bestMatches); }