Beispiel #1
0
        public void match_should_return_expected_result_when_controller_is_implicitly_versioned(string requestUri, string odataPath, bool allowImplicitVersioning)
        {
            // arrange
            const string rawApiVersion = default;
            var          apiVersion    = new ApiVersion(2, 0);

            void OnConfigure(ApiVersioningOptions options)
            {
                options.DefaultApiVersion = apiVersion;
                options.AssumeDefaultVersionWhenUnspecified = allowImplicitVersioning;
            }

            var url      = new Uri(requestUri);
            var context  = NewHttpContext(url, rawApiVersion, configure: OnConfigure);
            var route    = Mock.Of <IRouter>();
            var routeKey = (string)null;
            var values   = new RouteValueDictionary()
            {
                [nameof(odataPath)] = odataPath
            };
            var constraint = new VersionedODataPathRouteConstraint("odata", apiVersion);

            // act
            var result = constraint.Match(context, route, routeKey, values, IncomingRequest);

            // assert
            result.Should().BeTrue();
        }
        public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary <string, object> values, HttpRouteDirection routeDirection)
        {
            if (routeDirection == UriGeneration)
            {
                return(true);
            }

            if (!MatchAnyVersion && apiVersion != request.GetRequestedApiVersion())
            {
                return(false);
            }

            var properties = request.ApiVersionProperties();

            // determine whether this constraint can match any api version and no api version has otherwise been matched
            if (MatchAnyVersion && properties.RequestedApiVersion == null)
            {
                var options = request.GetApiVersioningOptions();

                // is implicitly matching an api version allowed?
                if (options.AssumeDefaultVersionWhenUnspecified || IsServiceDocumentOrMetadataRoute(values))
                {
                    var odata               = request.ODataApiVersionProperties();
                    var model               = new ApiVersionModel(odata.MatchingRoutes.Keys, Enumerable.Empty <ApiVersion>());
                    var selector            = options.ApiVersionSelector;
                    var requestedApiVersion = properties.RequestedApiVersion = selector.SelectVersion(request, model);

                    // if an api version is selected, determine if it corresponds to a route that has been previously matched
                    if (requestedApiVersion != null && odata.MatchingRoutes.TryGetValue(requestedApiVersion, out var routeName))
                    {
                        // create a new versioned path constraint on the fly and evaluate it. this sets up the underlying odata
                        // infrastructure such as the container, edm, etc. this has no bearing the action selector which will
                        // already select the correct action. without this the response may be incorrect, even if the correct
                        // action is selected and executed.
                        var constraint = new VersionedODataPathRouteConstraint(routeName, requestedApiVersion);
                        return(constraint.Match(request, route, parameterName, values, routeDirection));
                    }
                }
            }
            else if (!MatchAnyVersion && properties.RequestedApiVersion != apiVersion)
            {
                return(false);
            }

            request.DeleteRequestContainer(true);

            // by evaluating the remaining unversioned constraints, this will ultimately determine whether 400 or 404
            // is returned for an odata request
            foreach (var constraint in innerConstraints)
            {
                if (constraint.Match(request, route, parameterName, values, routeDirection))
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #3
0
        public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
        {
            if (routeDirection == UrlGeneration)
            {
                return(true);
            }

            var feature = httpContext.Features.Get <IApiVersioningFeature>();

            // determine whether this constraint can match any api version and no api version has otherwise been matched
            if (MatchAnyVersion && feature.RequestedApiVersion == null)
            {
                var options = httpContext.RequestServices.GetRequiredService <IOptions <ApiVersioningOptions> >().Value;

                // is implicitly matching an api version allowed?
                if (options.AssumeDefaultVersionWhenUnspecified || IsServiceDocumentOrMetadataRoute(values))
                {
                    var odata               = httpContext.ODataVersioningFeature();
                    var model               = new ApiVersionModel(odata.MatchingRoutes.Keys, Array.Empty <ApiVersion>());
                    var selector            = httpContext.RequestServices.GetRequiredService <IApiVersionSelector>();
                    var requestedApiVersion = feature.RequestedApiVersion = selector.SelectVersion(httpContext.Request, model);

                    // if an api version is selected, determine if it corresponds to a route that has been previously matched
                    if (requestedApiVersion != null && odata.MatchingRoutes.TryGetValue(requestedApiVersion, out var routeName))
                    {
                        // create a new versioned path constraint on the fly and evaluate it. this sets up the underlying odata
                        // infrastructure such as the container, edm, etc. this has no bearing the action selector which will
                        // already select the correct action. without this the response may be incorrect, even if the correct
                        // action is selected and executed.
                        var constraint = new VersionedODataPathRouteConstraint(routeName, requestedApiVersion);
                        return(constraint.Match(httpContext, route, routeKey, values, routeDirection));
                    }
                }
            }
            else if (!MatchAnyVersion && feature.RequestedApiVersion != apiVersion)
            {
                return(false);
            }

            httpContext.Request.DeleteRequestContainer(true);

            // by evaluating the remaining unversioned constraints, this will ultimately determine whether 400 or 404
            // is returned for an odata request
            foreach (var constraint in innerConstraints)
            {
                if (constraint.Match(httpContext, route, routeKey, values, routeDirection))
                {
                    return(true);
                }
            }

            return(false);
        }
        public void match_should_always_return_true_for_uri_resolution()
        {
            // arrange
            var request        = new HttpRequestMessage();
            var route          = new Mock <IHttpRoute>().Object;
            var parameterName  = (string)null;
            var values         = new Dictionary <string, object>();
            var routeDirection = UriGeneration;
            var constraint     = new VersionedODataPathRouteConstraint("odata", Default);

            // act
            var result = constraint.Match(request, route, parameterName, values, routeDirection);

            // assert
            result.Should().BeTrue();
        }
Beispiel #5
0
        public void match_should_always_return_true_for_uri_resolution()
        {
            // arrange
            var url         = new Uri("http://localhost");
            var httpContext = NewHttpContext(url, "1.0");
            var route       = Mock.Of <IRouter>();
            var routeKey    = (string)null;
            var values      = new RouteValueDictionary();
            var constraint  = new VersionedODataPathRouteConstraint("odata", Default);

            // act
            var result = constraint.Match(httpContext, route, routeKey, values, UrlGeneration);

            // assert
            result.Should().BeTrue();
        }
        static VersionedODataPathRouteConstraint NewVersionedODataPathRouteConstraint(
            HttpRequestMessage request,
            IEdmModel model,
            ApiVersion apiVersion,
            Action <ApiVersioningOptions> configure = default,
            string routePrefix = default)
        {
            var pathHandler        = new DefaultODataPathHandler();
            var conventions        = ODataRoutingConventions.CreateDefault();
            var configuration      = new HttpConfiguration();
            var routingConventions = Enumerable.Empty <IODataRoutingConvention>();
            var constraint         = new VersionedODataPathRouteConstraint("odata", apiVersion);

            configuration.AddApiVersioning(configure ?? new Action <ApiVersioningOptions>(_ => { }));
            configuration.MapVersionedODataRoute("odata", routePrefix, model, apiVersion);
            request.SetConfiguration(configuration);
            configuration.EnsureInitialized();

            return(constraint);
        }
Beispiel #7
0
        public void match_should_be_true_when_api_version_is_requested_in_query_string(string apiVersionValue)
        {
            // arrange
            var url        = new Uri("http://localhost/Tests(1)?api-version=" + apiVersionValue);
            var apiVersion = Parse(apiVersionValue);
            var context    = NewHttpContext(url, apiVersionValue);
            var route      = Mock.Of <IRouter>();
            var routeKey   = (string)null;
            var values     = new RouteValueDictionary()
            {
                ["odataPath"] = "Tests(1)"
            };
            var constraint = new VersionedODataPathRouteConstraint("odata", apiVersion);

            // act
            var result = constraint.Match(context, route, routeKey, values, IncomingRequest);

            // assert
            result.Should().BeTrue();
        }
Beispiel #8
0
        public void match_should_return_expected_result_when_requested_api_version_is_ambiguous(string odataPath, bool expected)
        {
            // arrange
            var url        = new Uri($"http://localhost/{odataPath}?api-version=1.0&api-version=2.0");
            var apiVersion = new ApiVersion(1, 0);
            var route      = Mock.Of <IRouter>();
            var routeKey   = (string)null;
            var values     = new RouteValueDictionary()
            {
                [nameof(odataPath)] = odataPath
            };
            var context    = NewHttpContext(url, "1.0");
            var constraint = new VersionedODataPathRouteConstraint("odata", apiVersion);

            // act
            var result = constraint.Match(context, route, routeKey, values, IncomingRequest);

            // assert
            result.Should().Be(expected);
        }
Beispiel #9
0
        public void match_should_return_expected_result_for_service_and_metadata_document(string requestUri, string odataPath, string apiVersionValue, bool expected)
        {
            // arrange
            const string rawApiVersion = default;
            var          url           = new Uri(requestUri);
            var          apiVersion    = Parse(apiVersionValue);
            var          context       = NewHttpContext(url, rawApiVersion);
            var          route         = Mock.Of <IRouter>();
            var          routeKey      = (string)null;
            var          values        = new RouteValueDictionary()
            {
                [nameof(odataPath)] = odataPath
            };
            var constraint = new VersionedODataPathRouteConstraint("odata", apiVersion);

            // act
            var result = constraint.Match(context, route, routeKey, values, IncomingRequest);

            // assert
            result.Should().Be(expected);
        }