public void Match_ReturnsFalse_IfODataPathCannotBeParsed()
        {
            var values = new Dictionary<string, object>() { { "odataPath", "NotAnODataPath" } };

            var constraint = new ODataPathRouteConstraint(_pathHandler, _model, _routeName, _conventions);
            Assert.False(constraint.Match(_request, null, null, values, HttpRouteDirection.UriResolution));
        }
        public void Match_ReturnsTrue_ForUriGeneration()
        {            
            var values = new Dictionary<string, object>();

            var constraint = new ODataPathRouteConstraint(_pathHandler, _model, _routeName, _conventions);
            Assert.True(constraint.Match(_request, null, null, values, HttpRouteDirection.UriGeneration));
        }
Example #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ODataRoute" /> class.
 /// </summary>
 /// <param name="routePrefix">The route prefix.</param>
 /// <param name="pathConstraint">The OData path constraint.</param>
 /// <param name="defaults">The default values for the route.</param>
 /// <param name="constraints">The route constraints.</param>
 /// <param name="dataTokens">The data tokens.</param>
 /// <param name="handler">The message handler for the route.</param>
 public ODataRoute(
     string routePrefix,
     ODataPathRouteConstraint pathConstraint,
     HttpRouteValueDictionary defaults,
     HttpRouteValueDictionary constraints,
     HttpRouteValueDictionary dataTokens,
     HttpMessageHandler handler)
     : this(routePrefix, (IHttpRouteConstraint)pathConstraint, defaults, constraints, dataTokens, handler)
 {
 }
        public void Match_ReturnsTrue_IfODataPathCanBeParsed()
        {
            var values = new Dictionary<string, object>() { { "odataPath", "$metadata" } };

            var constraint = new ODataPathRouteConstraint(_pathHandler, _model, _routeName, _conventions);
            Assert.True(constraint.Match(_request, null, null, values, HttpRouteDirection.UriResolution));

            Assert.Equal("Metadata", values["controller"]);
            Assert.Same(_model, _request.ODataProperties().Model);
            Assert.Same(_routeName, _request.ODataProperties().RouteName);
            Assert.Equal(_conventions, _request.ODataProperties().RoutingConventions);
            Assert.Same(_pathHandler, _request.ODataProperties().PathHandler);
        }
        public void Match_ThrowsHttpResponseException_IfPathParserThrowsODataException()
        {
            var values = new Dictionary<string, object>() { { "odataPath", "" } };
            _request.SetConfiguration(new HttpConfiguration() { IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always });
            Mock<IODataPathHandler> pathHandler = new Mock<IODataPathHandler>();
            string exceptionMessage = "NOOODATA";
            pathHandler.Setup(handler => handler.Parse(_model, "")).Throws(new ODataException(exceptionMessage));
            var constraint = new ODataPathRouteConstraint(pathHandler.Object, _model, _routeName, _conventions);

            var ex = Assert.Throws<HttpResponseException>(
                () => constraint.Match(_request, null, null, values, HttpRouteDirection.UriResolution));

            Assert.Equal(HttpStatusCode.NotFound, ex.Response.StatusCode);
            HttpError error = ex.Response.Content.ReadAsAsync<HttpError>().Result;
            Assert.Equal("The OData path is invalid.", error.Message);
            Assert.Equal(exceptionMessage, error.ExceptionMessage);
        }
        public void Match_DeterminesExpectedServiceRoot_ForFunctionCallWithEscapedSeparator(
            string prefixString,
            string oDataString)
        {
            // Arrange
            var originalRoot = "http://any/" + prefixString;
            var expectedRoot = originalRoot;

            if (!String.IsNullOrEmpty(prefixString))
            {
                originalRoot += "%2F";  // Escaped '/'
            }

            var oDataPath           = String.Format("Unbound(p0='{0}')", oDataString);
            var request             = new HttpRequestMessage(HttpMethod.Get, originalRoot + oDataPath);
            var httpRouteCollection = new HttpRouteCollection
            {
                { _routeName, new HttpRoute() },
            };

            request.SetConfiguration(new HttpConfiguration(httpRouteCollection));

            var builder = new ODataModelBuilder();

            builder.Function("Unbound").Returns <string>().Parameter <string>("p0");
            var model = builder.GetEdmModel();

            var pathHandler = new TestPathHandler();
            var constraint  = new ODataPathRouteConstraint(pathHandler, model, _routeName, _conventions);
            var values      = new Dictionary <string, object>
            {
                { ODataRouteConstants.ODataPath, Uri.UnescapeDataString(oDataPath) },
            };

            // Act
            var matched = constraint.Match(request, null, null, values, HttpRouteDirection.UriResolution);

            // Assert
            Assert.True(matched);
            Assert.NotNull(pathHandler.ServiceRoot);
            Assert.Equal(expectedRoot, pathHandler.ServiceRoot);
            Assert.NotNull(pathHandler.ODataPath);
            Assert.Equal(oDataPath, pathHandler.ODataPath);
        }
Example #7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ODataRoute" /> class.
        /// </summary>
        /// <param name="routePrefix">The route prefix.</param>
        /// <param name="pathConstraint">The OData path constraint.</param>
        /// <param name="defaults">The default values for the route.</param>
        /// <param name="constraints">The route constraints.</param>
        /// <param name="dataTokens">The data tokens.</param>
        /// <param name="handler">The message handler for the route.</param>
        public ODataRoute(
            string routePrefix,
            ODataPathRouteConstraint pathConstraint,
            HttpRouteValueDictionary defaults,
            HttpRouteValueDictionary constraints,
            HttpRouteValueDictionary dataTokens,
            HttpMessageHandler handler)
            : base(GetRouteTemplate(routePrefix), defaults, constraints, dataTokens, handler)
        {
            RoutePrefix         = routePrefix;
            PathRouteConstraint = pathConstraint;

            // We can only use our fast-path for link generation if there are no open brackets in the route prefix
            // that need to be replaced. If there are, fall back to the slow path.
            _canGenerateDirectLink = routePrefix != null && RoutePrefix.IndexOf('{') == -1;

            if (pathConstraint != null)
            {
                Constraints.Add(ODataRouteConstants.ConstraintName, pathConstraint);
            }
        }
Example #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ODataRoute" /> class.
        /// </summary>
        /// <param name="routePrefix">The route prefix.</param>
        /// <param name="pathConstraint">The OData path constraint.</param>
        /// <param name="defaults">The default values for the route.</param>
        /// <param name="constraints">The route constraints.</param>
        /// <param name="dataTokens">The data tokens.</param>
        /// <param name="handler">The message handler for the route.</param>
        public ODataRoute(
            string routePrefix,
            ODataPathRouteConstraint pathConstraint,
            HttpRouteValueDictionary defaults,
            HttpRouteValueDictionary constraints,
            HttpRouteValueDictionary dataTokens,
            HttpMessageHandler handler)
            : base(GetRouteTemplate(routePrefix), defaults, constraints, dataTokens, handler)
        {
            RoutePrefix = routePrefix;
            PathRouteConstraint = pathConstraint;

            // We can only use our fast-path for link generation if there are no open brackets in the route prefix
            // that need to be replaced. If there are, fall back to the slow path.
            _canGenerateDirectLink = routePrefix != null && RoutePrefix.IndexOf('{') == -1;

            if (pathConstraint != null)
            {
                Constraints.Add(ODataRouteConstants.ConstraintName, pathConstraint);
            }
        }
        public void Match_ReturnsFalse_IfODataPathHasNotImplementedSegment()
        {
            // Arrange
            var request = new HttpRequestMessage(HttpMethod.Get, "http://any/Customers/$count");
            HttpRouteCollection httpRouteCollection = new HttpRouteCollection();

            httpRouteCollection.Add(_routeName, new HttpRoute());
            request.SetConfiguration(new HttpConfiguration(httpRouteCollection));

            var values = new Dictionary <string, object>()
            {
                { "odataPath", "Customers/$count" }
            };
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

            builder.EntitySet <Customer>("Customers");
            IEdmModel model      = builder.GetEdmModel();
            var       constraint = new ODataPathRouteConstraint(_pathHandler, model, _routeName, _conventions);

            // Act & Assert
            Assert.False(constraint.Match(request, null, null, values, HttpRouteDirection.UriResolution));
        }
        public void Match_DeterminesExpectedServiceRoot_ForMetadataWithEscapedSeparator(string prefixString)
        {
            // Arrange
            var originalRoot = "http://any/" + prefixString;
            var expectedRoot = originalRoot;

            if (!String.IsNullOrEmpty(prefixString))
            {
                originalRoot += "%2F";  // Escaped '/'
            }

            var request             = new HttpRequestMessage(HttpMethod.Get, originalRoot + "$metadata");
            var httpRouteCollection = new HttpRouteCollection
            {
                { _routeName, new HttpRoute() },
            };

            request.SetConfiguration(new HttpConfiguration(httpRouteCollection));

            var pathHandler = new TestPathHandler();
            var constraint  = new ODataPathRouteConstraint(pathHandler, _model, _routeName, _conventions);
            var values      = new Dictionary <string, object>
            {
                { ODataRouteConstants.ODataPath, "$metadata" },
            };

            // Act
            var matched = constraint.Match(request, null, null, values, HttpRouteDirection.UriResolution);

            // Assert
            Assert.True(matched);
            Assert.NotNull(pathHandler.ServiceRoot);
            Assert.Equal(expectedRoot, pathHandler.ServiceRoot);
            Assert.NotNull(pathHandler.ODataPath);
            Assert.Equal("$metadata", pathHandler.ODataPath);
        }
        public void Match_ReturnsTrue_IfODataPathCanBeParsed()
        {
            // Arrange
            var request = new HttpRequestMessage(HttpMethod.Get, "http://any/odata/$metadata");
            HttpRouteCollection httpRouteCollection = new HttpRouteCollection();

            httpRouteCollection.Add(_routeName, new HttpRoute());
            request.SetConfiguration(new HttpConfiguration(httpRouteCollection));

            var values = new Dictionary <string, object>()
            {
                { "odataPath", "$metadata" }
            };
            var constraint = new ODataPathRouteConstraint(_pathHandler, _model, _routeName, _conventions);

            // Act & Assert
            Assert.True(constraint.Match(request, null, null, values, HttpRouteDirection.UriResolution));

            Assert.Equal("Metadata", values["controller"]);
            Assert.Same(_model, request.ODataProperties().Model);
            Assert.Same(_routeName, request.ODataProperties().RouteName);
            Assert.Equal(_conventions, request.ODataProperties().RoutingConventions);
            Assert.Same(_pathHandler, request.ODataProperties().PathHandler);
        }
        /// <summary>
        /// Maps the specified OData route. When the <paramref name="defaultHandler"/> is non-<c>null</c>, it will map
        /// it as the handler for the route.
        /// </summary>
        /// <param name="configuration">The server configuration.</param>
        /// <param name="routeName">The name of the route to map.</param>
        /// <param name="routePrefix">The prefix to add to the OData route's path template.</param>
        /// <param name="model">The EDM model to use for parsing OData paths.</param>
        /// <param name="pathHandler">The <see cref="IODataPathHandler" /> to use for parsing the OData path.</param>
        /// <param name="routingConventions">
        /// The OData routing conventions to use for controller and action selection.
        /// </param>
        /// <param name="defaultHandler">The default <see cref="HttpMessageHandler"/> for this route.</param>
        /// <returns>The added <see cref="ODataRoute"/>.</returns>
        public static ODataRoute MapODataServiceRoute(this HttpConfiguration configuration, string routeName,
            string routePrefix, IEdmModel model, IODataPathHandler pathHandler,
            IEnumerable<IODataRoutingConvention> routingConventions, HttpMessageHandler defaultHandler)
        {
            if (configuration == null)
            {
                throw Error.ArgumentNull("configuration");
            }

            // We have a more specific overload to map batch handlers that creates a different route for the batch
            // endpoint instead of mapping that handler as the per route handler. Given that HttpMessageHandler is a
            // base type of ODataBatchHandler, it's possible the compiler will call this overload instead of the one
            // for the batch handler, so we detect that case and call the appropiate overload for the user.
            // The case in which the compiler picks the wrong overload is:
            // HttpRequestMessageHandler batchHandler = new DefaultODataBatchHandler(httpServer);
            // config.Routes.MapODataServiceRoute("routeName", "routePrefix", model, batchHandler);
            if (defaultHandler != null)
            {
                ODataBatchHandler batchHandler = defaultHandler as ODataBatchHandler;
                if (batchHandler != null)
                {
                    return MapODataServiceRoute(configuration, routeName, routePrefix, model, batchHandler);
                }
            }

            HttpRouteCollection routes = configuration.Routes;
            routePrefix = RemoveTrailingSlash(routePrefix);

            DefaultODataPathHandler odataPathHandler = pathHandler as DefaultODataPathHandler;
            if (odataPathHandler != null)
            {
                odataPathHandler.ResolverSetttings = configuration.GetResolverSettings();
            }

            ODataPathRouteConstraint routeConstraint =
                new ODataPathRouteConstraint(pathHandler, model, routeName, routingConventions);
            ODataRoute route = new ODataRoute(
                routePrefix,
                routeConstraint,
                defaults: null,
                constraints: null,
                dataTokens: null,
                handler: defaultHandler);
            routes.Add(routeName, route);
            return route;
        }
        public static ODataRoute MapODataServiceRoute(this HttpConfiguration configuration, string routeName,
            string routePrefix, IEdmModel model, IODataPathHandler pathHandler,
            IEnumerable<IODataRoutingConvention> routingConventions, ODataBatchHandler batchHandler)
        {
            if (configuration == null)
            {
                throw Error.ArgumentNull("configuration");
            }

            HttpRouteCollection routes = configuration.Routes;
            routePrefix = RemoveTrailingSlash(routePrefix);

            if (batchHandler != null)
            {
                batchHandler.ODataRouteName = routeName;
                string batchTemplate = String.IsNullOrEmpty(routePrefix) ? ODataRouteConstants.Batch
                    : routePrefix + '/' + ODataRouteConstants.Batch;
                routes.MapHttpBatchRoute(routeName + "Batch", batchTemplate, batchHandler);
            }

            DefaultODataPathHandler odataPathHandler = pathHandler as DefaultODataPathHandler;
            if (odataPathHandler != null)
            {
                odataPathHandler.ResolverSetttings = configuration.GetResolverSettings();
            }

            ODataPathRouteConstraint routeConstraint =
                new ODataPathRouteConstraint(pathHandler, model, routeName, routingConventions);
            ODataRoute route = new ODataRoute(routePrefix, routeConstraint);
            routes.Add(routeName, route);
            return route;
        }
Example #14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ODataRoute" /> class.
 /// </summary>
 /// <param name="routePrefix">The route prefix.</param>
 /// <param name="pathConstraint">The OData path constraint.</param>
 public ODataRoute(string routePrefix, ODataPathRouteConstraint pathConstraint)
     : this(routePrefix, pathConstraint, defaults: null, constraints: null, dataTokens: null, handler: null)
 {
 }
        public void Match_ReturnsFalse_IfODataPathHasNotImplementedSegment()
        {
            // Arrange
            var request = new HttpRequestMessage(HttpMethod.Get, "http://any/Customers(1)/OpenProperty");
            HttpRouteCollection httpRouteCollection = new HttpRouteCollection();
            httpRouteCollection.Add(_routeName, new HttpRoute());
            request.SetConfiguration(new HttpConfiguration(httpRouteCollection));

            var model = new EdmModel();
            var customer = new EdmEntityType(
                namespaceName: "NS",
                name: "Customer",
                baseType: null,
                isAbstract: false,
                isOpen: true);
            customer.AddKeys(customer.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32));
            model.AddElement(customer);
            var container = new EdmEntityContainer("NS", "Container");
            container.AddEntitySet("Customers", customer);
            model.AddElement(container);

            var values = new Dictionary<string, object>() { { "odataPath", "Customers(1)/OpenProperty" } };
            var constraint = new ODataPathRouteConstraint(_pathHandler, model, _routeName, _conventions);

            // Act & Assert
            Assert.False(constraint.Match(request, null, null, values, HttpRouteDirection.UriResolution));
        }
        public void Match_DeterminesExpectedServiceRoot_ForFunctionCallWithEscapedSeparator(
            string prefixString,
            string oDataString)
        {
            // Arrange
            var originalRoot = "http://any/" + prefixString;
            var expectedRoot = originalRoot;
            if (!String.IsNullOrEmpty(prefixString))
            {
                originalRoot += "%2F";  // Escaped '/'
            }

            var oDataPath = String.Format("Unbound(p0='{0}')", oDataString);
            var request = new HttpRequestMessage(HttpMethod.Get, originalRoot + oDataPath);
            var httpRouteCollection = new HttpRouteCollection
            {
                { _routeName, new HttpRoute() },
            };
            request.SetConfiguration(new HttpConfiguration(httpRouteCollection));

            var builder = new ODataModelBuilder();
            builder.Function("Unbound").Returns<string>().Parameter<string>("p0");
            var model = builder.GetEdmModel();

            var pathHandler = new TestPathHandler();
            var constraint = new ODataPathRouteConstraint(pathHandler, model, _routeName, _conventions);
            var values = new Dictionary<string, object>
            {
                { ODataRouteConstants.ODataPath, Uri.UnescapeDataString(oDataPath) },
            };

            // Act
            var matched = constraint.Match(request, null, null, values, HttpRouteDirection.UriResolution);

            // Assert
            Assert.True(matched);
            Assert.NotNull(pathHandler.ServiceRoot);
            Assert.Equal(expectedRoot, pathHandler.ServiceRoot);
            Assert.NotNull(pathHandler.ODataPath);
            Assert.Equal(oDataPath, pathHandler.ODataPath);
        }
        public void Match_DeterminesExpectedServiceRoot_ForMetadataWithEscapedSeparator(string prefixString)
        {
            // Arrange
            var originalRoot = "http://any/" + prefixString;
            var expectedRoot = originalRoot;
            if (!String.IsNullOrEmpty(prefixString))
            {
                originalRoot += "%2F";  // Escaped '/'
            }

            var request = new HttpRequestMessage(HttpMethod.Get, originalRoot + "$metadata");
            var httpRouteCollection = new HttpRouteCollection
            {
                { _routeName, new HttpRoute() },
            };
            request.SetConfiguration(new HttpConfiguration(httpRouteCollection));

            var pathHandler = new TestPathHandler();
            var constraint = new ODataPathRouteConstraint(pathHandler, _model, _routeName, _conventions);
            var values = new Dictionary<string, object>
            {
                { ODataRouteConstants.ODataPath, "$metadata" },
            };

            // Act
            var matched = constraint.Match(request, null, null, values, HttpRouteDirection.UriResolution);

            // Assert
            Assert.True(matched);
            Assert.NotNull(pathHandler.ServiceRoot);
            Assert.Equal(expectedRoot, pathHandler.ServiceRoot);
            Assert.NotNull(pathHandler.ODataPath);
            Assert.Equal("$metadata", pathHandler.ODataPath);
        }
        public void Match_ReturnsTrue_IfODataPathCanBeParsed()
        {
            // Arrange
            var request = new HttpRequestMessage(HttpMethod.Get, "http://any/odata/$metadata");
            HttpRouteCollection httpRouteCollection = new HttpRouteCollection();
            httpRouteCollection.Add(_routeName, new HttpRoute());
            request.SetConfiguration(new HttpConfiguration(httpRouteCollection));

            var values = new Dictionary<string, object>() { { "odataPath", "$metadata" } };
            var constraint = new ODataPathRouteConstraint(_pathHandler, _model, _routeName, _conventions);

            // Act & Assert
            Assert.True(constraint.Match(request, null, null, values, HttpRouteDirection.UriResolution));

            Assert.Equal("Metadata", values["controller"]);
            Assert.Same(_model, request.ODataProperties().Model);
            Assert.Same(_routeName, request.ODataProperties().RouteName);
            Assert.Equal(_conventions, request.ODataProperties().RoutingConventions);
            Assert.Same(_pathHandler, request.ODataProperties().PathHandler);
        }
Example #19
0
 public DynamicODataRoute(string routePrefix, ODataPathRouteConstraint pathConstraint)
     : base(routePrefix, pathConstraint)
 {
     _canGenerateDirectLink = routePrefix != null && RoutePrefix.IndexOf('{') == -1;
 }
        public void Match_ReturnsFalse_IfODataPathHasNotImplementedSegment()
        {
            // Arrange
            var request = new HttpRequestMessage(HttpMethod.Get, "http://any/Customers/$count");
            HttpRouteCollection httpRouteCollection = new HttpRouteCollection();
            httpRouteCollection.Add(_routeName, new HttpRoute());
            request.SetConfiguration(new HttpConfiguration(httpRouteCollection));

            var values = new Dictionary<string, object>() { { "odataPath", "Customers/$count" } };
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            builder.EntitySet<Customer>("Customers");
            IEdmModel model = builder.GetEdmModel();
            var constraint = new ODataPathRouteConstraint(_pathHandler, model, _routeName, _conventions);

            // Act & Assert
            Assert.False(constraint.Match(request, null, null, values, HttpRouteDirection.UriResolution));
        }
        public static ODataRoute MapODataServiceRoute(this HttpRouteCollection routes, string routeName,
            string routePrefix, IEdmModel model, IODataPathHandler pathHandler,
            IEnumerable<IODataRoutingConvention> routingConventions, ODataBatchHandler batchHandler)
        {
            if (routes == null)
            {
                throw Error.ArgumentNull("routes");
            }

            if (!String.IsNullOrEmpty(routePrefix))
            {
                int prefixLastIndex = routePrefix.Length - 1;
                if (routePrefix[prefixLastIndex] == '/')
                {
                    // Remove the last trailing slash if it has one.
                    routePrefix = routePrefix.Substring(0, routePrefix.Length - 1);
                }
            }

            if (batchHandler != null)
            {
                batchHandler.ODataRouteName = routeName;
                string batchTemplate = String.IsNullOrEmpty(routePrefix) ? ODataRouteConstants.Batch
                    : routePrefix + '/' + ODataRouteConstants.Batch;
                routes.MapHttpBatchRoute(routeName + "Batch", batchTemplate, batchHandler);
            }

            ODataPathRouteConstraint routeConstraint =
                new ODataPathRouteConstraint(pathHandler, model, routeName, routingConventions);
            ODataRoute route = new ODataRoute(routePrefix, routeConstraint);
            routes.Add(routeName, route);
            return route;
        }
Example #22
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ODataRoute" /> class.
 /// </summary>
 /// <param name="routePrefix">The route prefix.</param>
 /// <param name="pathConstraint">The OData path constraint.</param>
 public ODataRoute(string routePrefix, ODataPathRouteConstraint pathConstraint)
     : this(routePrefix, pathConstraint, defaults : null, constraints : null, dataTokens : null, handler : null)
 {
 }
        public void Match_ReturnsFalse_IfODataPathCannotBeParsed()
        {
            // Arrange
            var request = new HttpRequestMessage(HttpMethod.Get, "http://any/NotAnODataPath");
            HttpRouteCollection httpRouteCollection = new HttpRouteCollection();
            httpRouteCollection.Add(_routeName, new HttpRoute());
            request.SetConfiguration(new HttpConfiguration(httpRouteCollection));

            var values = new Dictionary<string, object>() { { "odataPath", "NotAnODataPath" } };
            var constraint = new ODataPathRouteConstraint(_pathHandler, _model, _routeName, _conventions);

            // Act & Assert
            Assert.False(constraint.Match(request, null, null, values, HttpRouteDirection.UriResolution));
        }