public static IList<string> GetPaths(FilterQueryOption filterOption, string separator = ".")
        {
            var findAnyAll = new FindNavigationFilterOptions();
            findAnyAll.Find(filterOption.FilterClause.Expression);

            return findAnyAll.GetPaths(separator);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ODataQueryOptions"/> class based on the incoming request and some metadata information from 
        /// the <see cref="ODataQueryContext"/>.
        /// </summary>
        /// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information</param>
        /// <param name="request">The incoming request message</param>
        public ODataQueryOptions(ODataQueryContext context, HttpRequestMessage request)
        {
            if (context == null)
            {
                throw Error.ArgumentNull("context");
            }

            if (request == null)
            {
                throw Error.ArgumentNull("request");
            }

            // remember the context
            Context = context;

            // Parse the query from request Uri
            RawValues = new ODataRawQueryOptions();
            IEnumerable<KeyValuePair<string, string>> queryParameters = request.GetQueryNameValuePairs();
            foreach (KeyValuePair<string, string> kvp in queryParameters)
            {
                switch (kvp.Key)
                {
                    case "$filter":
                        RawValues.Filter = kvp.Value;
                        ThrowIfEmpty(kvp.Value, "$filter");
                        Filter = new FilterQueryOption(kvp.Value, context);
                        break;
                    case "$orderby":
                        RawValues.OrderBy = kvp.Value;
                        ThrowIfEmpty(kvp.Value, "$orderby");
                        OrderBy = new OrderByQueryOption(kvp.Value, context);
                        break;
                    case "$top":
                        RawValues.Top = kvp.Value;
                        ThrowIfEmpty(kvp.Value, "$top");
                        Top = new TopQueryOption(kvp.Value, context);
                        break;
                    case "$skip":
                        RawValues.Skip = kvp.Value;
                        ThrowIfEmpty(kvp.Value, "$skip");
                        Skip = new SkipQueryOption(kvp.Value, context);
                        break;
                    case "$select":
                        RawValues.Select = kvp.Value;
                        break;
                    case "$inlinecount":
                        RawValues.InlineCount = kvp.Value;
                        break;
                    case "$expand":
                        RawValues.Expand = kvp.Value;
                        break;
                    case "$skiptoken":
                        RawValues.SkipToken = kvp.Value;
                        break;
                    default:
                        // we don't throw if we can't recognize the query
                        break;
                }
            }
        }
        public void CanConstructValidFilterQuery(string filterValue)
        {
            var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel();
            var context = new ODataQueryContext(model, typeof(Customer), "Customers");
            var filter = new FilterQueryOption(filterValue, context);

            Assert.Same(context, filter.Context);
            Assert.Equal(filterValue, filter.RawValue);
        }
        public static WhereClause BindFilterQueryOption(FilterQueryOption filterQuery)
        {
            if (filterQuery != null)
            {
                NHibernateFilterBinder binder = new NHibernateFilterBinder(filterQuery.Context.Model);
                return new WhereClause
                {
                    Clause = "where " + binder.BindFilter(filterQuery) + Environment.NewLine,
                    PositionalParameters = binder._positionalParmeters.ToArray()
                };
            }

            return _emptyWhereClause;
        }
        public void GetQueryNodeParsesQuery()
        {
            var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel();
            var context = new ODataQueryContext(model, typeof(Customer), "Customers");
            var filter = new FilterQueryOption("Name eq 'MSFT'", context);
            var node = filter.QueryNode;

            Assert.Equal(QueryNodeKind.BinaryOperator, node.Expression.Kind);
            var binaryNode = node.Expression as BinaryOperatorQueryNode;
            Assert.Equal(BinaryOperatorKind.Equal, binaryNode.OperatorKind);
            Assert.Equal(QueryNodeKind.Constant, binaryNode.Right.Kind);
            Assert.Equal("MSFT", ((ConstantQueryNode)binaryNode.Right).Value);
            Assert.Equal(QueryNodeKind.PropertyAccess, binaryNode.Left.Kind);
            var propertyAccessNode = binaryNode.Left as PropertyAccessQueryNode;
            Assert.Equal("Name", propertyAccessNode.Property.Name);
        }
Example #6
0
        public void GetQueryNodeParsesQuery()
        {
            var model   = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel();
            var context = new ODataQueryContext(model, typeof(Customer), "Customers");
            var filter  = new FilterQueryOption("Name eq 'MSFT'", context);
            var node    = filter.QueryNode;

            Assert.Equal(QueryNodeKind.BinaryOperator, node.Expression.Kind);
            var binaryNode = node.Expression as BinaryOperatorQueryNode;

            Assert.Equal(BinaryOperatorKind.Equal, binaryNode.OperatorKind);
            Assert.Equal(QueryNodeKind.Constant, binaryNode.Right.Kind);
            Assert.Equal("MSFT", ((ConstantQueryNode)binaryNode.Right).Value);
            Assert.Equal(QueryNodeKind.PropertyAccess, binaryNode.Left.Kind);
            var propertyAccessNode = binaryNode.Left as PropertyAccessQueryNode;

            Assert.Equal("Name", propertyAccessNode.Property.Name);
        }
Example #7
0
        public void ApplyToEnums_ThrowsNotSupported_ForStringFunctions(string filter, string exceptionMessage)
        {
            // Arrange
            var builder = new ODataConventionModelBuilder();

            builder.EntitySet <EnumModel>("EnumModels");
            var model = builder.GetEdmModel();

            var context      = new ODataQueryContext(model, typeof(EnumModel), "EnumModels");
            var filterOption = new FilterQueryOption(filter, context);
            IEnumerable <EnumModel> enumModels = EnumModelTestData;

            // Act
            Assert.Throws <ODataException>(
                () => filterOption.ApplyTo(enumModels.AsQueryable(), new ODataQuerySettings {
                HandleNullPropagation = HandleNullPropagationOption.True
            }),
                exceptionMessage
                );
        }
Example #8
0
        public void ApplyToEnums_ReturnsCorrectQueryable(string filter, int[] enumModelIds)
        {
            // Arrange
            var model        = GetEnumModel();
            var context      = new ODataQueryContext(model, typeof(EnumModel));
            var filterOption = new FilterQueryOption(filter, context);
            IEnumerable <EnumModel> enumModels = EnumModelTestData;

            // Act
            IQueryable queryable = filterOption.ApplyTo(enumModels.AsQueryable(), new ODataQuerySettings {
                HandleNullPropagation = HandleNullPropagationOption.True
            });

            // Assert
            Assert.NotNull(queryable);
            IEnumerable <EnumModel> actualCustomers = Assert.IsAssignableFrom <IEnumerable <EnumModel> >(queryable);

            Assert.Equal(
                enumModelIds,
                actualCustomers.Select(enumModel => enumModel.Id));
        }
        public void TestFilterVisitor()
        {
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            builder.EntitySet<Bar>("Bar");

            ODataQueryContext context = new ODataQueryContext(builder.GetEdmModel(), typeof(Bar));
            //ODataQueryOptions<Customer> query = new ODataQueryOptions<Customer>(context, new HttpRequestMessage(HttpMethod.Get, "http://server/?$top=10"));

            FilterQueryOption f = new FilterQueryOption("startswith(BarString,'b') eq true", context);
            var fo = new FindNavigationFilterOptions();
            fo.Find(f.FilterClause.Expression);
            List<string> pathsString = fo.GetPaths();
            CollectionAssert.AreEqual(pathsString, new string[0]);

            f = new FilterQueryOption("F/FooId eq 1", context);
            fo = new FindNavigationFilterOptions();
            fo.Find(f.FilterClause.Expression);
            pathsString = fo.GetPaths();
            CollectionAssert.AreEqual(pathsString, new[] { "F" });

            f = new FilterQueryOption("(startswith(BarString,'b') eq true) and (not (Foos/any(x1: x1/B/BarId eq 1)))", context);
            fo = new FindNavigationFilterOptions();
            fo.Find(f.FilterClause.Expression);
            pathsString = fo.GetPaths();
            CollectionAssert.AreEqual(pathsString, new[] { "Foos.B" });

            f = new FilterQueryOption("Foos/any(x1: x1/B/BarId eq 1)", context);
            fo = new FindNavigationFilterOptions();
            fo.Find(f.FilterClause.Expression);
            pathsString = fo.GetPaths();
            CollectionAssert.AreEqual(pathsString, new[] { "Foos.B" });

            f = new FilterQueryOption("F/Bars/any(x1: x1/BarId eq 1)", context);
            fo = new FindNavigationFilterOptions();
            fo.Find(f.FilterClause.Expression);
            pathsString = fo.GetPaths();
            CollectionAssert.AreEqual(pathsString, new[] { "F.Bars" });


        }
        public void CanConstructValidAnyQueryOverComplexCollectionProperty()
        {
            var model          = new ODataModelBuilder().Add_Customer_EntityType_With_CollectionProperties().Add_Customers_EntitySet().Add_Address_ComplexType().GetEdmModel();
            var context        = new ODataQueryContext(model, typeof(Customer), "Customers");
            var filter         = new FilterQueryOption("Addresses/any(a: a/HouseNumber eq 1)", context);
            var node           = filter.QueryNode;
            var anyNode        = node.Expression as AnyQueryNode;
            var aParameter     = anyNode.Parameters.SingleOrDefault(p => p.Name == "a");
            var aParameterType = aParameter.ParameterType.Definition as IEdmComplexType;

            Assert.NotNull(aParameter);

            // There's currently a bug here. For now, the test checks for the presence of the bug (as a reminder to fix
            // the test once the bug is fixed).
            // The following asserts show the behavior with the bug and should be removed once the bug is fixed.
            Assert.Null(aParameterType);
            Assert.Equal("a", aParameter.Name);

            // TODO: Enable once Uri Parser sets parameters of Any/All bound to CollectionProperty correctly
            // The following asserts show the behavior without the bug, and should be enabled once the bug is fixed.
            //Assert.NotNull(aParameterType);
            //Assert.Equal("Address", aParameter.Name);
        }
        public void CanConstructValidAnyQueryOverComplexCollectionProperty()
        {
            var model = new ODataModelBuilder().Add_Customer_EntityType_With_CollectionProperties().Add_Customers_EntitySet().Add_Address_ComplexType().GetEdmModel();
            var context = new ODataQueryContext(model, typeof(Customer), "Customers");
            var filter = new FilterQueryOption("Addresses/any(a: a/HouseNumber eq 1)", context);
            var node = filter.QueryNode;
            var anyNode = node.Expression as AnyQueryNode;
            var aParameter = anyNode.Parameters.SingleOrDefault(p => p.Name == "a");
            var aParameterType = aParameter.ParameterType.Definition as IEdmComplexType;

            Assert.NotNull(aParameter);
            Assert.NotNull(aParameterType);
            Assert.Equal("Address", aParameter.Name); 
        }
Example #12
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ODataQueryOptions"/> class based on the incoming request and some metadata information from
        /// the <see cref="ODataQueryContext"/>.
        /// </summary>
        /// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information.</param>
        /// <param name="request">The incoming request message.</param>
        public ODataQueryOptions(ODataQueryContext context, HttpRequestMessage request)
        {
            if (context == null)
            {
                throw Error.ArgumentNull("context");
            }

            if (request == null)
            {
                throw Error.ArgumentNull("request");
            }

            if (request.GetConfiguration() != null)
            {
                _assembliesResolver = request.GetConfiguration().Services.GetAssembliesResolver();
            }

            // fallback to the default assemblies resolver if none available.
            _assembliesResolver = _assembliesResolver ?? new DefaultAssembliesResolver();

            // remember the context and request
            Context = context;
            Request = request;

            // Parse the query from request Uri
            RawValues = new ODataRawQueryOptions();
            IEnumerable <KeyValuePair <string, string> > queryParameters = request.GetQueryNameValuePairs();

            foreach (KeyValuePair <string, string> kvp in queryParameters)
            {
                switch (kvp.Key)
                {
                case "$filter":
                    RawValues.Filter = kvp.Value;
                    ThrowIfEmpty(kvp.Value, "$filter");
                    Filter = new FilterQueryOption(kvp.Value, context);
                    break;

                case "$orderby":
                    RawValues.OrderBy = kvp.Value;
                    ThrowIfEmpty(kvp.Value, "$orderby");
                    OrderBy = new OrderByQueryOption(kvp.Value, context);
                    break;

                case "$top":
                    RawValues.Top = kvp.Value;
                    ThrowIfEmpty(kvp.Value, "$top");
                    Top = new TopQueryOption(kvp.Value, context);
                    break;

                case "$skip":
                    RawValues.Skip = kvp.Value;
                    ThrowIfEmpty(kvp.Value, "$skip");
                    Skip = new SkipQueryOption(kvp.Value, context);
                    break;

                case "$select":
                    RawValues.Select = kvp.Value;
                    break;

                case "$inlinecount":
                    RawValues.InlineCount = kvp.Value;
                    ThrowIfEmpty(kvp.Value, "$inlinecount");
                    InlineCount = new InlineCountQueryOption(kvp.Value, context);
                    break;

                case "$expand":
                    RawValues.Expand = kvp.Value;
                    break;

                case "$format":
                    RawValues.Format = kvp.Value;
                    break;

                case "$skiptoken":
                    RawValues.SkipToken = kvp.Value;
                    break;

                default:
                    // we don't throw if we can't recognize the query
                    break;
                }
            }

            Validator = new ODataQueryValidator();
        }
 private static WhereClause ToFilterQuery(FilterQueryOption filterQuery)
 {
     return NHibernateFilterBinder.BindFilterQueryOption(filterQuery);
 }
        public void ApplyTo_WithUnTypedContext_Throws_InvalidOperation()
        {
            CustomersModelWithInheritance model = new CustomersModelWithInheritance();
            ODataQueryContext context = new ODataQueryContext(model.Model, model.Customer);
            FilterQueryOption filter = new FilterQueryOption("Id eq 42", context);
            IQueryable queryable = new Mock<IQueryable>().Object;

            Assert.Throws<NotSupportedException>(() => filter.ApplyTo(queryable, new ODataQuerySettings()),
                "The query option is not bound to any CLR type. 'ApplyTo' is only supported with a query option bound to a CLR type.");
        }
        public void Property_FilterClause_WorksWithUnTypedContext()
        {
            // Arrange
            CustomersModelWithInheritance model = new CustomersModelWithInheritance();
            ODataQueryContext context = new ODataQueryContext(model.Model, model.Customer);
            FilterQueryOption filter = new FilterQueryOption("ID eq 42", context);

            // Act & Assert
            Assert.NotNull(filter.FilterClause);
        }
Example #16
0
        public override void Validate(FilterQueryOption filterQueryOption, ODataValidationSettings settings)
        {
            base.Validate(filterQueryOption, settings);

            if (!visited)
            { 
                throw new ODataException("$filter query must contain ID property");
            }
        }
        public void ApplyToEnums_ReturnsCorrectQueryable(string filter, int[] enumModelIds)
        {
            // Arrange
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<EnumModel>("EnumModels");
            var model = builder.GetEdmModel();
            
            var context = new ODataQueryContext(model, typeof(EnumModel), "EnumModels");
            var filterOption = new FilterQueryOption(filter, context);
            IEnumerable<EnumModel> enumModels = EnumModelTestData;

            // Act
            IQueryable queryable = filterOption.ApplyTo(enumModels.AsQueryable(), new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.True });

            // Assert
            Assert.NotNull(queryable);
            IEnumerable<EnumModel> actualCustomers = Assert.IsAssignableFrom<IEnumerable<EnumModel>>(queryable);
            Assert.Equal(
                enumModelIds,
                actualCustomers.Select(enumModel => enumModel.Id));
        }
        public void CanConstructValidAnyQueryOverPrimitiveCollectionProperty()
        {
            var model = new ODataModelBuilder().Add_Customer_EntityType_With_CollectionProperties().Add_Customers_EntitySet().GetEdmModel();
            var context = new ODataQueryContext(model, typeof(Customer));
            var filter = new FilterQueryOption("Aliases/any(a: a eq 'alias')", context);
            var node = filter.FilterClause;
            var anyNode = node.Expression as AnyNode;
            var aParameter = anyNode.RangeVariables.SingleOrDefault(p => p.Name == "a");
            var aParameterType = aParameter.TypeReference.Definition as IEdmPrimitiveType;

            Assert.NotNull(aParameter);

            Assert.NotNull(aParameterType);
            Assert.Equal("a", aParameter.Name);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ODataQueryOptions"/> class based on the incoming request and some metadata information from
        /// the <see cref="ODataQueryContext"/>.
        /// </summary>
        /// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information</param>
        /// <param name="request">The incoming request message</param>
        public ODataQueryOptions(ODataQueryContext context, HttpRequestMessage request)
        {
            if (context == null)
            {
                throw Error.ArgumentNull("context");
            }

            if (request == null)
            {
                throw Error.ArgumentNull("request");
            }

            // remember the context
            Context = context;

            // Parse the query from request Uri
            RawValues = new ODataRawQueryOptions();
            IEnumerable <KeyValuePair <string, string> > queryParameters = request.GetQueryNameValuePairs();

            foreach (KeyValuePair <string, string> kvp in queryParameters)
            {
                switch (kvp.Key)
                {
                case "$filter":
                    RawValues.Filter = kvp.Value;
                    ThrowIfEmpty(kvp.Value, "$filter");
                    Filter = new FilterQueryOption(kvp.Value, context);
                    break;

                case "$orderby":
                    RawValues.OrderBy = kvp.Value;
                    ThrowIfEmpty(kvp.Value, "$orderby");
                    OrderBy = new OrderByQueryOption(kvp.Value, context);
                    break;

                case "$top":
                    RawValues.Top = kvp.Value;
                    ThrowIfEmpty(kvp.Value, "$top");
                    Top = new TopQueryOption(kvp.Value, context);
                    break;

                case "$skip":
                    RawValues.Skip = kvp.Value;
                    ThrowIfEmpty(kvp.Value, "$skip");
                    Skip = new SkipQueryOption(kvp.Value, context);
                    break;

                case "$select":
                    RawValues.Select = kvp.Value;
                    break;

                case "$inlinecount":
                    RawValues.InlineCount = kvp.Value;
                    break;

                case "$expand":
                    RawValues.Expand = kvp.Value;
                    break;

                case "$skiptoken":
                    RawValues.SkipToken = kvp.Value;
                    break;

                default:
                    // we don't throw if we can't recognize the query
                    break;
                }
            }
        }
 protected string BindFilter(FilterQueryOption filterQuery)
 {
     return BindFilterClause(filterQuery.FilterClause);
 }
        public void ApplyTo_Throws_Null_AssembliesResolver()
        {
            // Arrange
            var model = new ODataModelBuilder().Add_Customer_EntityType_With_CollectionProperties().Add_Customers_EntitySet().Add_Address_ComplexType().GetEdmModel();
            var context = new ODataQueryContext(model, typeof(Customer), "Customers");
            var filter = new FilterQueryOption("Addresses/any(a: a/HouseNumber eq 1)", context);

            // Act & Assert
            Assert.ThrowsArgumentNull(() => filter.ApplyTo(new Customer[0].AsQueryable(), new ODataQuerySettings(), null), "assembliesResolver");
        }
        public void CanTurnOffValidationForFilter()
        {
            ODataValidationSettings settings = new ODataValidationSettings() { AllowedFunctions = AllowedFunctions.AllDateTimeFunctions };
            ODataQueryContext context = ValidationTestHelper.CreateCustomerContext();
            FilterQueryOption option = new FilterQueryOption("substring(Name,8,1) eq '7'", context);

            Assert.Throws<ODataException>(() =>
                option.Validate(settings),
                "Function 'substring' is not allowed. To allow it, set the 'AllowedFunctions' property on QueryableAttribute or QueryValidationSettings.");

            option.Validator = null;
            Assert.DoesNotThrow(() => option.Validate(settings));
        }
        public void ApplyTo_Returns_Correct_Queryable(string filter, int[] customerIds)
        {
            // Arrange
            var model = new ODataModelBuilder()
                            .Add_Order_EntityType()
                            .Add_Customer_EntityType_With_Address()
                            .Add_CustomerOrders_Relationship()
                            .Add_Customer_EntityType_With_CollectionProperties()
                            .Add_Customers_EntitySet()
                            .GetEdmModel();
            var context = new ODataQueryContext(model, typeof(Customer), "Customers");
            var filterOption = new FilterQueryOption(filter, context);
            IEnumerable<Customer> customers = CustomerFilterTestData;

            // Act
            IQueryable queryable = filterOption.ApplyTo(customers.AsQueryable(), new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.True });

            // Assert
            Assert.NotNull(queryable);
            IEnumerable<Customer> actualCustomers = Assert.IsAssignableFrom<IEnumerable<Customer>>(queryable);
            Assert.Equal(
                customerIds,
                actualCustomers.Select(customer => customer.CustomerId));
        }
        public void ApplyTo_ReturnsCorrectQueryable_PropertyAlias(string filter, int[] propertyAliasIds)
        {
            // Arrange
            var model = GetPropertyAliasModel();
            var context = new ODataQueryContext(model, typeof(PropertyAlias));
            var filterOption = new FilterQueryOption(filter, context);
            IEnumerable<PropertyAlias> propertyAliases = PropertyAliasTestData;

            // Act
            IQueryable queryable = filterOption.ApplyTo(
                propertyAliases.AsQueryable(),
                new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.True });

            // Assert
            Assert.NotNull(queryable);
            IEnumerable<PropertyAlias> actualPropertyAliases = Assert.IsAssignableFrom<IEnumerable<PropertyAlias>>(queryable);
            Assert.Equal(
                propertyAliasIds,
                actualPropertyAliases.Select(propertyAlias => propertyAlias.Id));
        }
        public void ApplyToEnums_ThrowsNotSupported_ForStringFunctions(string filter, string exceptionMessage)
        {
            // Arrange
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<EnumModel>("EnumModels");
            var model = builder.GetEdmModel();

            var context = new ODataQueryContext(model, typeof(EnumModel), "EnumModels");
            var filterOption = new FilterQueryOption(filter, context);
            IEnumerable<EnumModel> enumModels = EnumModelTestData;

            // Act
            Assert.Throws<ODataException>(
                () => filterOption.ApplyTo(enumModels.AsQueryable(), new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.True }),
                exceptionMessage
            );
        }
        public void CanConstructValidAnyQueryOverComplexCollectionProperty()
        {
            var model = new ODataModelBuilder().Add_Customer_EntityType_With_CollectionProperties().Add_Customers_EntitySet().Add_Address_ComplexType().GetEdmModel();
            var context = new ODataQueryContext(model, typeof(Customer), "Customers");
            var filter = new FilterQueryOption("Addresses/any(a: a/HouseNumber eq 1)", context);
            var node = filter.QueryNode;
            var anyNode = node.Expression as AnyQueryNode;
            var aParameter = anyNode.Parameters.SingleOrDefault(p => p.Name == "a");
            var aParameterType = aParameter.ParameterType.Definition as IEdmComplexType;

            Assert.NotNull(aParameter);

            // There's currently a bug here. For now, the test checks for the presence of the bug (as a reminder to fix
            // the test once the bug is fixed).
            // The following asserts show the behavior with the bug and should be removed once the bug is fixed.
            Assert.Null(aParameterType);
            Assert.Equal("a", aParameter.Name);

            // TODO: Enable once Uri Parser sets parameters of Any/All bound to CollectionProperty correctly
            // The following asserts show the behavior without the bug, and should be enabled once the bug is fixed.
            //Assert.NotNull(aParameterType);
            //Assert.Equal("Address", aParameter.Name); 
        }