internal ControllerSelectionContext( HttpRequestMessage request, Func <HttpRequestMessage, string?> controllerName, Lazy <ConcurrentDictionary <string, HttpControllerDescriptorGroup> > controllerInfoCache) { Request = request; requestProperties = request.ApiVersionProperties(); this.controllerName = new Lazy <string?>(() => controllerName(Request)); this.controllerInfoCache = controllerInfoCache; RouteData = request.GetRouteData(); conventionRouteCandidates = new Lazy <CandidateAction[]?>(GetConventionRouteCandidates); directRouteCandidates = new Lazy <CandidateAction[]?>(() => RouteData?.GetDirectRouteCandidates()); allVersions = new Lazy <ApiVersionModel>(CreateAggregatedModel); }
/// <summary> /// Gets the current API versioning request properties. /// </summary> /// <param name="request">The <see cref="HttpRequestMessage">request</see> to get the API versioning properties for.</param> /// <returns>The current <see cref="ApiVersionRequestProperties">API versioning properties</see>.</returns> public static ApiVersionRequestProperties ApiVersionProperties(this HttpRequestMessage request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (!request.Properties.TryGetValue(ApiVersionPropertiesKey, out ApiVersionRequestProperties properties)) { request.Properties[ApiVersionPropertiesKey] = properties = new ApiVersionRequestProperties(request); } return(properties); }
/// <summary> /// Gets the current API versioning request properties. /// </summary> /// <param name="request">The <see cref="HttpRequestMessage">request</see> to get the API versioning properties for.</param> /// <returns>The current <see cref="ApiVersionRequestProperties">API versioning properties</see>.</returns> public static ApiVersionRequestProperties ApiVersionProperties(this HttpRequestMessage request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (!request.Properties.TryGetValue(ApiVersionPropertiesKey, out ApiVersionRequestProperties properties)) { var forceRouteConstraintEvaluation = !request.Properties.ContainsKey(RoutingContextKey); request.Properties[ApiVersionPropertiesKey] = properties = new ApiVersionRequestProperties(request); if (forceRouteConstraintEvaluation) { request.GetConfiguration()?.Routes.GetRouteData(request); } } return(properties); }
public void http_context_should_return_raw_api_version_from_query_string_without_configuration() { // arrange var query = new Mock <IQueryCollection>(); var request = new Mock <HttpRequest>(); var httpContext = new Mock <HttpContext>(); var items = new Dictionary <object, object>(); query.SetupGet(q => q["api-version"]).Returns(new StringValues("42.0")); request.SetupGet(r => r.Query).Returns(query.Object); httpContext.SetupGet(c => c.Request).Returns(request.Object); httpContext.SetupProperty(c => c.RequestServices, Mock.Of <IServiceProvider>()); httpContext.SetupProperty(c => c.Items, items); items["MS_ApiVersionRequestProperties"] = new ApiVersionRequestProperties(httpContext.Object); // act var result = httpContext.Object.ApiVersionProperties().RawApiVersion; // assert result.Should().Be("42.0"); }
/// <summary> /// Gets the current API versioning request properties. /// </summary> /// <param name="request">The <see cref="HttpRequestMessage">request</see> to get the API versioning properties for.</param> /// <returns>The current <see cref="ApiVersionRequestProperties">API versioning properties</see>.</returns> public static ApiVersionRequestProperties ApiVersionProperties(this HttpRequestMessage request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (request.Properties.TryGetValue(ApiVersionPropertiesKey, out ApiVersionRequestProperties properties)) { return(properties); } var forceRouteConstraintEvaluation = !request.Properties.ContainsKey(RoutingContextKey); request.Properties[ApiVersionPropertiesKey] = properties = new ApiVersionRequestProperties(request); if (forceRouteConstraintEvaluation && request.GetConfiguration() is HttpConfiguration configuration) { // HACK: do NOT use 'HttpRouteCollection.GetRouteData' because it can result in a LockRecursionException when hosted on IIS // REF: https://github.com/microsoft/referencesource/blob/master/System.Web/Routing/RouteCollection.cs#L159 var routes = configuration.Routes; var context = request.GetRequestContext(); var virtualPathRoot = context?.VirtualPathRoot ?? routes.VirtualPathRoot ?? string.Empty; // HACK: do NOT use a normal 'for' loop here because the IIS implementation does not support indexing foreach (var route in routes) { if (route.GetRouteData(virtualPathRoot, request) is not null) { break; } } } return(properties); }
static ApiVersion GetRequestedApiVersionOrReturnBadRequest(HttpRequestMessage request, ApiVersionRequestProperties properties) { Contract.Requires(request != null); Contract.Requires(properties != null); try { return(properties.RequestedApiVersion); } catch (AmbiguousApiVersionException ex) { var error = new ODataError() { ErrorCode = "AmbiguousApiVersion", Message = ex.Message }; throw new HttpResponseException(request.CreateResponse(BadRequest, error)); } }