コード例 #1
0
        public void Validate_DepthChecks_DollarLevels(string expand, int maxExpansionDepth)
        {
            // Arrange
            var validator = new SelectExpandQueryValidator();
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<ODataLevelsTest.LevelsEntity>("Entities");
            IEdmModel model = builder.GetEdmModel();
            var context = new ODataQueryContext(model, typeof(ODataLevelsTest.LevelsEntity));
            var selectExpandQueryOption = new SelectExpandQueryOption(null, expand, context);
            selectExpandQueryOption.LevelsMaxLiteralExpansionDepth = 1;

            // Act & Assert
            Assert.Throws<ODataException>(
                () => validator.Validate(
                    selectExpandQueryOption,
                    new ODataValidationSettings { MaxExpansionDepth = maxExpansionDepth }),
                String.Format(
                    CultureInfo.CurrentCulture,
                    "The request includes a $expand path which is too deep. The maximum depth allowed is {0}. " +
                    "To increase the limit, set the 'MaxExpansionDepth' property on EnableQueryAttribute or ODataValidationSettings.",
                    maxExpansionDepth));

            Assert.DoesNotThrow(
                () => validator.Validate(
                    selectExpandQueryOption,
                    new ODataValidationSettings { MaxExpansionDepth = maxExpansionDepth + 1 }));
        }
コード例 #2
0
        /// <summary>
        /// Validates a <see cref="TopQueryOption" />.
        /// </summary>
        /// <param name="selectExpandQueryOption">The $select and $expand query.</param>
        /// <param name="validationSettings">The validation settings.</param>
        public virtual void Validate(SelectExpandQueryOption selectExpandQueryOption, ODataValidationSettings validationSettings)
        {
            if (selectExpandQueryOption == null)
            {
                throw Error.ArgumentNull("selectExpandQueryOption");
            }

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

            IEdmModel model = selectExpandQueryOption.Context.Model;
            ValidateRestrictions(selectExpandQueryOption.SelectExpandClause, model);

            if (validationSettings.MaxExpansionDepth > 0)
            {
                if (selectExpandQueryOption.LevelsMaxLiteralExpansionDepth > validationSettings.MaxExpansionDepth)
                {
                    throw new ODataException(Error.Format(
                        SRResources.InvalidExpansionDepthValue,
                        "LevelsMaxLiteralExpansionDepth",
                        "MaxExpansionDepth"));
                }

                ValidateDepth(selectExpandQueryOption.SelectExpandClause, validationSettings.MaxExpansionDepth);
            }
        }
コード例 #3
0
        public static object Bind(object entity, ODataQuerySettings settings, SelectExpandQueryOption selectExpandQuery)
        {
            Contract.Assert(entity != null);

            SelectExpandBinder binder = new SelectExpandBinder(settings, selectExpandQuery);
            return binder.Bind(entity);
        }
コード例 #4
0
        public void Bind_GeneratedExpression_ContainsExpandedObject()
        {
            // Arrange
            SelectExpandQueryOption selectExpand = new SelectExpandQueryOption("Orders", "Orders,Orders($expand=Customer)", _context);
            IPropertyMapper mapper = new IdentityPropertyMapper();
            _model.Model.SetAnnotationValue(_model.Order, new DynamicPropertyDictionaryAnnotation(typeof(Order).GetProperty("OrderProperties")));

            // Act
            IQueryable queryable = SelectExpandBinder.Bind(_queryable, _settings, new DefaultAssembliesResolver(), selectExpand);

            // Assert
            IEnumerator enumerator = queryable.GetEnumerator();
            Assert.True(enumerator.MoveNext());
            var partialCustomer = Assert.IsAssignableFrom<SelectExpandWrapper<Customer>>(enumerator.Current);
            Assert.False(enumerator.MoveNext());
            Assert.Null(partialCustomer.Instance);
            IEnumerable<SelectExpandWrapper<Order>> innerOrders = partialCustomer.Container
                .ToDictionary(mapper)["Orders"] as IEnumerable<SelectExpandWrapper<Order>>;
            Assert.NotNull(innerOrders);
            SelectExpandWrapper<Order> partialOrder = innerOrders.Single();
            Assert.Same(_queryable.First().Orders.First(), partialOrder.Instance);
            object customer = partialOrder.Container.ToDictionary(mapper)["Customer"];
            SelectExpandWrapper<Customer> innerInnerCustomer = Assert.IsAssignableFrom<SelectExpandWrapper<Customer>>(customer);
            Assert.Same(_queryable.First(), innerInnerCustomer.Instance);
        }
コード例 #5
0
        public static IQueryable Bind(IQueryable queryable, ODataQuerySettings settings, SelectExpandQueryOption selectExpandQuery)
        {
            Contract.Assert(queryable != null);

            SelectExpandBinder binder = new SelectExpandBinder(settings, selectExpandQuery);
            return binder.Bind(queryable);
        }
コード例 #6
0
        public void ValidateDoesNotThrow_IfExpansionDepthIsZero()
        {
            string expand = "Orders/Customer/Orders/Customer/Orders/Customer";
            SelectExpandQueryValidator validator = new SelectExpandQueryValidator();
            SelectExpandQueryOption selectExpandQueryOption = new SelectExpandQueryOption(null, expand, _queryContext);

            Assert.DoesNotThrow(
                () => validator.Validate(selectExpandQueryOption, new ODataValidationSettings { MaxExpansionDepth = 0 }));
        }
コード例 #7
0
        public void ValidateThrowException_IfNotNavigable()
        {
            CustomersModelWithInheritance model = new CustomersModelWithInheritance();
            model.Model.SetAnnotationValue(model.Customer, new ClrTypeAnnotation(typeof(Customer)));
            ODataQueryContext queryContext = new ODataQueryContext(model.Model, typeof(Customer));
            model.Model.SetAnnotationValue(model.Customer.FindProperty("Orders"), new QueryableRestrictionsAnnotation(new QueryableRestrictions{NotNavigable=true}));

            string select = "Orders";
            SelectExpandQueryValidator validator = new SelectExpandQueryValidator();
            SelectExpandQueryOption selectExpandQueryOption = new SelectExpandQueryOption(select, null, queryContext);
            Assert.Throws<ODataException>(
                () => validator.Validate(selectExpandQueryOption, new ODataValidationSettings()),
                "The property 'Orders' cannot be used for navigation.");
        }
コード例 #8
0
        public SelectExpandBinder(ODataQuerySettings settings, SelectExpandQueryOption selectExpandQuery)
        {
            Contract.Assert(settings != null);
            Contract.Assert(selectExpandQuery != null);
            Contract.Assert(selectExpandQuery.Context != null);
            Contract.Assert(selectExpandQuery.Context.Model != null);
            Contract.Assert(settings.HandleNullPropagation != HandleNullPropagationOption.Default);

            _selectExpandQuery = selectExpandQuery;
            _context = selectExpandQuery.Context;
            _model = _context.Model;
            _modelID = ModelContainer.GetModelID(_model);
            _settings = settings;
        }
コード例 #9
0
        public void Bind_ReturnsIEdmObject_WithRightEdmType()
        {
            // Arrange
            SelectExpandQueryOption selectExpand = new SelectExpandQueryOption(select: "ID", expand: null, context: _context);

            // Act
            IQueryable queryable = SelectExpandBinder.Bind(_queryable, _settings, selectExpand);

            // Assert
            Assert.NotNull(queryable);
            IEdmTypeReference edmType = _model.Model.GetEdmTypeReference(queryable.GetType());
            Assert.NotNull(edmType);
            Assert.True(edmType.IsCollection());
            Assert.Same(_model.Customer, edmType.AsCollection().ElementType().Definition);
        }
コード例 #10
0
        public void Validate_DepthChecks(string expand, int maxExpansionDepth)
        {
            // Arrange
            SelectExpandQueryValidator validator = new SelectExpandQueryValidator();
            SelectExpandQueryOption selectExpandQueryOption = new SelectExpandQueryOption(null, expand, _queryContext);

            // Act & Assert
            Assert.Throws<ODataException>(
                () => validator.Validate(selectExpandQueryOption, new ODataValidationSettings { MaxExpansionDepth = maxExpansionDepth }),
                String.Format(CultureInfo.CurrentCulture, "The request includes a $expand path which is too deep. The maximum depth allowed is {0}. " +
                "To increase the limit, set the 'MaxExpansionDepth' property on EnableQueryAttribute or ODataValidationSettings.", maxExpansionDepth));

            Assert.DoesNotThrow(
                () => validator.Validate(selectExpandQueryOption, new ODataValidationSettings { MaxExpansionDepth = maxExpansionDepth + 1 }));
        }
コード例 #11
0
        public void ValidateThrowException_IfBaseOrDerivedClassPropertyNotNavigable(string className, string propertyName)
        {
            CustomersModelWithInheritance model = new CustomersModelWithInheritance();
            model.Model.SetAnnotationValue(model.SpecialCustomer, new ClrTypeAnnotation(typeof(Customer)));
            ODataQueryContext queryContext = new ODataQueryContext(model.Model, typeof(Customer));
            EdmEntityType classType = (className == "Customer") ? model.Customer : model.SpecialCustomer;
            model.Model.SetAnnotationValue(classType.FindProperty(propertyName), new QueryableRestrictionsAnnotation(new QueryableRestrictions { NotNavigable = true }));

            string select = "NS.SpecialCustomer/" + propertyName;
            SelectExpandQueryValidator validator = new SelectExpandQueryValidator();
            SelectExpandQueryOption selectExpandQueryOption = new SelectExpandQueryOption(select, null, queryContext);
            Assert.Throws<ODataException>(
                () => validator.Validate(selectExpandQueryOption, new ODataValidationSettings()),
                String.Format(CultureInfo.InvariantCulture, "The property '{0}' cannot be used for navigation.", propertyName));
        }
コード例 #12
0
        /// <summary>
        /// Validates a <see cref="TopQueryOption" />.
        /// </summary>
        /// <param name="selectExpandQueryOption">The $select and $expand query.</param>
        /// <param name="validationSettings">The validation settings.</param>
        public virtual void Validate(SelectExpandQueryOption selectExpandQueryOption, ODataValidationSettings validationSettings)
        {
            if (selectExpandQueryOption == null)
            {
                throw Error.ArgumentNull("selectExpandQueryOption");
            }

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

            if (validationSettings.MaxExpansionDepth > 0)
            {
                ValidateDepth(selectExpandQueryOption.SelectExpandClause, validationSettings.MaxExpansionDepth);
            }
        }
コード例 #13
0
        /// <summary>
        /// Validates a <see cref="TopQueryOption" />.
        /// </summary>
        /// <param name="selectExpandQueryOption">The $select and $expand query.</param>
        /// <param name="validationSettings">The validation settings.</param>
        public virtual void Validate(SelectExpandQueryOption selectExpandQueryOption, ODataValidationSettings validationSettings)
        {
            if (selectExpandQueryOption == null)
            {
                throw Error.ArgumentNull("selectExpandQueryOption");
            }

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

            IEdmModel model = selectExpandQueryOption.Context.Model;
            ValidateRestrictions(selectExpandQueryOption.SelectExpandClause, model);

            if (validationSettings.MaxExpansionDepth > 0)
            {
                ValidateDepth(selectExpandQueryOption.SelectExpandClause, validationSettings.MaxExpansionDepth);
            }
        }
コード例 #14
0
        public void Bind_GeneratedExpression_ContainsExpandedObject()
        {
            // Arrange
            SelectExpandQueryOption selectExpand = new SelectExpandQueryOption("Orders,Orders/Customer", "Orders,Orders/Customer", _context);

            // Act
            IQueryable queryable = SelectExpandBinder.Bind(_queryable, _settings, selectExpand);

            // Assert
            IEnumerator enumerator = queryable.GetEnumerator();
            Assert.True(enumerator.MoveNext());
            var partialCustomer = Assert.IsAssignableFrom<SelectExpandWrapper<Customer>>(enumerator.Current);
            Assert.False(enumerator.MoveNext());
            Assert.Null(partialCustomer.Instance);
            IEnumerable<SelectExpandWrapper<Order>> innerOrders = partialCustomer.Container.ToDictionary()["Orders"] as IEnumerable<SelectExpandWrapper<Order>>;
            Assert.NotNull(innerOrders);
            SelectExpandWrapper<Order> partialOrder = innerOrders.Single();
            Assert.Same(_queryable.First().Orders.First(), partialOrder.Instance);
            SelectExpandWrapper<Customer> innerInnerCustomer = Assert.IsAssignableFrom<SelectExpandWrapper<Customer>>(partialOrder.Container.ToDictionary()["Customer"]);
            Assert.Same(_queryable.First(), innerInnerCustomer.Instance);
        }
コード例 #15
0
        public void Validate_Throws_LevelsMaxLiteralExpansionDepthGreaterThanMaxExpansionDepth()
        {
            // Arrange
            string expand = "Parent($levels=2)";
            var validator = new SelectExpandQueryValidator();
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<ODataLevelsTest.LevelsEntity>("Entities");
            IEdmModel model = builder.GetEdmModel();
            var context = new ODataQueryContext(model, typeof(ODataLevelsTest.LevelsEntity));
            var selectExpandQueryOption = new SelectExpandQueryOption(null, expand, context);
            selectExpandQueryOption.LevelsMaxLiteralExpansionDepth = 4;

            // Act & Assert
            Assert.Throws<ODataException>(
                () => validator.Validate(
                    selectExpandQueryOption,
                    new ODataValidationSettings { MaxExpansionDepth = 3 }),
                "'LevelsMaxLiteralExpansionDepth' should be less than or equal to 'MaxExpansionDepth'.");
        }
コード例 #16
0
        private static StringBuilder ODataContextUriBuilder(string scheme, string host, string path, EntitySet entitySet, SelectExpandQueryOption selectQueryOption)
        {
            StringBuilder contextUriBuilder = ODataContextUriBuilder(scheme, host, path, entitySet);

            if (selectQueryOption?.RawValue.Equals("$select=*", StringComparison.Ordinal) == true)
            {
                contextUriBuilder.Append("(*)");
            }
            else if (selectQueryOption?.PropertyPaths.Count > 0)
            {
                contextUriBuilder.AppendFormat(CultureInfo.InvariantCulture, "({0})", string.Join(",", selectQueryOption.PropertyPaths.Select(p => p.Property.Name)));
            }

            return(contextUriBuilder);
        }
コード例 #17
0
 /// <summary>
 /// Returns a <see cref="string"/> containing the the @odata.context.
 /// </summary>
 /// <param name="metadataLevel">The OData metadata level for the current request.</param>
 /// <param name="scheme">The scheme, which should be HTTP or HTTPS.</param>
 /// <param name="host">The host (e.g. odataservice.org).</param>
 /// <param name="path">The path (e.g. /odata/...)</param>
 /// <param name="entitySet">The <see cref="EntitySet"/>.</param>
 /// <param name="selectQueryOption">The $select query option.</param>
 /// <returns>A <see cref="string"/> containing the the @odata.context.</returns>
 public static string ODataContext(ODataMetadataLevel metadataLevel, string scheme, string host, string path, EntitySet entitySet, SelectExpandQueryOption selectQueryOption)
 => metadataLevel != ODataMetadataLevel.None ? ODataContextUriBuilder(scheme, host, path, entitySet, selectQueryOption).ToString() : default;
コード例 #18
0
        public void ProcessLevelsCorrectly_WithNestedLevels()
        {
            // Arrange
            var model   = ODataLevelsTest.GetEdmModel();
            var context = new ODataQueryContext(
                model,
                model.FindDeclaredType("Microsoft.AspNetCore.OData.Tests.Query.LevelsEntity"));

            context.RequestContainer = new MockServiceProvider();
            var selectExpand = new SelectExpandQueryOption(
                select: null,
                expand: "Parent($expand=DerivedAncestors($levels=2);$levels=max)",
                context: context);

            selectExpand.LevelsMaxLiteralExpansionDepth = 4;

            // Act
            SelectExpandClause clause = selectExpand.ProcessLevels();

            // Assert
            Assert.True(clause.AllSelected);
            Assert.Single(clause.SelectedItems);

            // Level 1 of Parent.
            var parent = Assert.IsType <ExpandedNavigationSelectItem>(clause.SelectedItems.Single());

            Assert.Equal(
                "Parent",
                ((NavigationPropertySegment)parent.PathToNavigationProperty.FirstSegment).NavigationProperty.Name);
            Assert.Null(parent.LevelsOption);

            var clauseOfParent = parent.SelectAndExpand;

            Assert.True(clauseOfParent.AllSelected);
            Assert.Equal(2, clauseOfParent.SelectedItems.Count());

            // Level 1 of DerivedAncestors.
            var derivedAncestors = Assert.Single(clauseOfParent.SelectedItems.OfType <ExpandedNavigationSelectItem>().Where(
                                                     item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment &&
                                                     ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "DerivedAncestors"));

            Assert.Null(derivedAncestors.LevelsOption);

            var clauseOfDerivedAncestors = derivedAncestors.SelectAndExpand;

            Assert.True(clauseOfDerivedAncestors.AllSelected);
            Assert.Single(clauseOfDerivedAncestors.SelectedItems);

            // Level 2 of DerivedAncestors.
            derivedAncestors = Assert.IsType <ExpandedNavigationSelectItem>(clauseOfDerivedAncestors.SelectedItems.Single());
            Assert.Equal(
                "DerivedAncestors",
                ((NavigationPropertySegment)derivedAncestors.PathToNavigationProperty.FirstSegment).NavigationProperty.Name);
            Assert.Null(derivedAncestors.LevelsOption);

            clauseOfDerivedAncestors = derivedAncestors.SelectAndExpand;
            Assert.True(clauseOfDerivedAncestors.AllSelected);
            Assert.Empty(clauseOfDerivedAncestors.SelectedItems);

            // Level 2 of Parent.
            parent = Assert.Single(clauseOfParent.SelectedItems.OfType <ExpandedNavigationSelectItem>().Where(
                                       item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment &&
                                       ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "Parent"));
            Assert.Null(parent.LevelsOption);

            clauseOfParent = parent.SelectAndExpand;
            Assert.True(clauseOfParent.AllSelected);
            Assert.Single(clauseOfParent.SelectedItems);

            // Level 1 of DerivedAncestors.
            derivedAncestors = Assert.Single(clauseOfParent.SelectedItems.OfType <ExpandedNavigationSelectItem>().Where(
                                                 item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment &&
                                                 ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "DerivedAncestors"));
            Assert.Null(derivedAncestors.LevelsOption);

            clauseOfDerivedAncestors = derivedAncestors.SelectAndExpand;
            Assert.True(clauseOfDerivedAncestors.AllSelected);
            Assert.Single(clauseOfDerivedAncestors.SelectedItems);

            // Level 2 of DerivedAncestors.
            derivedAncestors = Assert.IsType <ExpandedNavigationSelectItem>(clauseOfDerivedAncestors.SelectedItems.Single());
            Assert.Equal(
                "DerivedAncestors",
                ((NavigationPropertySegment)derivedAncestors.PathToNavigationProperty.FirstSegment).NavigationProperty.Name);
            Assert.Null(derivedAncestors.LevelsOption);

            clauseOfDerivedAncestors = derivedAncestors.SelectAndExpand;
            Assert.True(clauseOfDerivedAncestors.AllSelected);
            Assert.Empty(clauseOfDerivedAncestors.SelectedItems);
        }
コード例 #19
0
        public void ProcessLevelsCorrectly_WithMultipleProperties()
        {
            // Arrange
            var model   = ODataLevelsTest.GetEdmModel();
            var context = new ODataQueryContext(
                model,
                model.FindDeclaredType("Microsoft.AspNetCore.OData.Tests.Query.LevelsEntity"));

            context.RequestContainer = new MockServiceProvider();
            var selectExpand = new SelectExpandQueryOption(
                select: null,
                expand: "Parent($expand=Parent($levels=max),DerivedAncestors($levels=2;$select=ID)),BaseEntities($levels=2)",
                context: context);

            selectExpand.LevelsMaxLiteralExpansionDepth = 3;

            // Act
            SelectExpandClause clause = selectExpand.ProcessLevels();

            // Assert
            Assert.True(clause.AllSelected);
            Assert.Equal(2, clause.SelectedItems.Count());

            // Top level Parent.
            var parent = Assert.Single(clause.SelectedItems.OfType <ExpandedNavigationSelectItem>().Where(
                                           item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment &&
                                           ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "Parent"));

            Assert.Null(parent.LevelsOption);

            var clauseOfParent = parent.SelectAndExpand;

            Assert.True(clauseOfParent.AllSelected);
            Assert.Equal(2, clauseOfParent.SelectedItems.Count());

            // Level 1 of inline Parent.
            var inlineParent = Assert.Single(clauseOfParent.SelectedItems.OfType <ExpandedNavigationSelectItem>().Where(
                                                 item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment &&
                                                 ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "Parent"));

            Assert.Null(inlineParent.LevelsOption);

            // Level 2 of inline Parent.
            var inlineParentClause = inlineParent.SelectAndExpand;

            Assert.True(inlineParentClause.AllSelected);
            Assert.Single(inlineParentClause.SelectedItems);

            inlineParent = Assert.IsType <ExpandedNavigationSelectItem>(inlineParentClause.SelectedItems.Single());
            Assert.Equal(
                "Parent",
                ((NavigationPropertySegment)inlineParent.PathToNavigationProperty.FirstSegment).NavigationProperty.Name);
            Assert.Null(inlineParent.LevelsOption);

            inlineParentClause = inlineParent.SelectAndExpand;
            Assert.True(inlineParentClause.AllSelected);
            Assert.Empty(inlineParentClause.SelectedItems);

            // Level 1 of inline DerivedAncestors.
            var inlineDerivedAncestors = Assert.Single(clauseOfParent.SelectedItems.OfType <ExpandedNavigationSelectItem>().Where(
                                                           item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment &&
                                                           ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "DerivedAncestors"));

            Assert.Null(inlineDerivedAncestors.LevelsOption);

            // Level 2 of inline DerivedAncestors.
            var inlineDerivedAncestorsClause = inlineDerivedAncestors.SelectAndExpand;

            Assert.False(inlineDerivedAncestorsClause.AllSelected);
            Assert.Equal(3, inlineDerivedAncestorsClause.SelectedItems.Count());

            var idItem = Assert.Single(inlineDerivedAncestorsClause.SelectedItems.OfType <PathSelectItem>().Where(
                                           item => item.SelectedPath.FirstSegment is PropertySegment));

            Assert.Equal("ID", ((PropertySegment)idItem.SelectedPath.FirstSegment).Property.Name);

            var derivedAncestorsItem = Assert.Single(inlineDerivedAncestorsClause.SelectedItems.OfType <PathSelectItem>().Where(
                                                         item => item.SelectedPath.FirstSegment is NavigationPropertySegment));

            Assert.Equal(
                "DerivedAncestors",
                ((NavigationPropertySegment)derivedAncestorsItem.SelectedPath.FirstSegment).NavigationProperty.Name);

            inlineDerivedAncestors = Assert.Single(inlineDerivedAncestorsClause.SelectedItems.OfType <ExpandedNavigationSelectItem>());
            Assert.Equal(
                "DerivedAncestors",
                ((NavigationPropertySegment)inlineDerivedAncestors.PathToNavigationProperty.FirstSegment).NavigationProperty.Name);
            Assert.Null(inlineDerivedAncestors.LevelsOption);

            inlineDerivedAncestorsClause = inlineDerivedAncestors.SelectAndExpand;
            Assert.False(inlineDerivedAncestorsClause.AllSelected);
            Assert.Single(inlineDerivedAncestorsClause.SelectedItems);

            idItem = Assert.Single(inlineDerivedAncestorsClause.SelectedItems.OfType <PathSelectItem>());
            Assert.Equal("ID", ((PropertySegment)idItem.SelectedPath.FirstSegment).Property.Name);

            // Level 1 of BaseEntities.
            var baseEntities = Assert.Single(clause.SelectedItems.OfType <ExpandedNavigationSelectItem>().Where(
                                                 item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment &&
                                                 ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "BaseEntities"));

            Assert.Null(baseEntities.LevelsOption);

            // Level 2 of BaseEntities.
            var baseEntitiesClause = baseEntities.SelectAndExpand;

            Assert.True(baseEntitiesClause.AllSelected);
            Assert.Single(baseEntitiesClause.SelectedItems);

            baseEntities = Assert.IsType <ExpandedNavigationSelectItem>(baseEntitiesClause.SelectedItems.Single());
            Assert.Equal(
                "BaseEntities",
                ((NavigationPropertySegment)baseEntities.PathToNavigationProperty.FirstSegment).NavigationProperty.Name);
            Assert.Null(baseEntities.LevelsOption);

            baseEntitiesClause = baseEntities.SelectAndExpand;
            Assert.True(baseEntitiesClause.AllSelected);
            Assert.Empty(baseEntitiesClause.SelectedItems);
        }
コード例 #20
0
        public void ProcessLevelsCorrectly_NotAllSelected()
        {
            // Arrange
            var model   = ODataLevelsTest.GetEdmModel();
            var context = new ODataQueryContext(
                model,
                model.FindDeclaredType("Microsoft.AspNetCore.OData.Tests.Query.LevelsEntity"));

            context.RequestContainer = new MockServiceProvider();
            var selectExpand = new SelectExpandQueryOption(
                select: "Name",
                expand: "Parent($select=ID;$levels=max)",
                context: context);

            // Act
            SelectExpandClause clause = selectExpand.ProcessLevels();

            // Assert
            // Level 1.
            Assert.False(clause.AllSelected);
            Assert.Equal(2, clause.SelectedItems.Count());

            var nameSelectItem = Assert.Single(clause.SelectedItems.OfType <PathSelectItem>().Where(
                                                   item => item.SelectedPath.FirstSegment is PropertySegment));

            Assert.Equal("Name", ((PropertySegment)nameSelectItem.SelectedPath.FirstSegment).Property.Name);

            // Before ODL 7.6, the expand navigation property will be added as a select item (PathSelectItem).
            // After ODL 7.6 (include 7.6), the expand navigation property will not be added.
            // Comment the following codes for visibility later.

            /*
             * var parentSelectItem = Assert.Single(clause.SelectedItems.OfType<PathSelectItem>().Where(
             *  item => item.SelectedPath.FirstSegment is NavigationPropertySegment));
             * Assert.Equal(
             *  "Parent",
             *  ((NavigationPropertySegment)parentSelectItem.SelectedPath.FirstSegment).NavigationProperty.Name);
             */
            Assert.Empty(clause.SelectedItems.OfType <PathSelectItem>().Where(item => item.SelectedPath.FirstSegment is NavigationPropertySegment));

            var expandedItem = Assert.Single(clause.SelectedItems.OfType <ExpandedNavigationSelectItem>());

            Assert.Equal(
                "Parent",
                ((NavigationPropertySegment)expandedItem.PathToNavigationProperty.FirstSegment).NavigationProperty.Name);
            Assert.Null(expandedItem.LevelsOption);

            // Level 2.
            clause = expandedItem.SelectAndExpand;
            Assert.False(clause.AllSelected);
            Assert.Equal(3, clause.SelectedItems.Count());

            var idSelectItem = Assert.Single(clause.SelectedItems.OfType <PathSelectItem>().Where(
                                                 item => item.SelectedPath.FirstSegment is PropertySegment));

            Assert.Equal("ID", ((PropertySegment)idSelectItem.SelectedPath.FirstSegment).Property.Name);

            var parentSelectItem = Assert.Single(clause.SelectedItems.OfType <PathSelectItem>().Where(
                                                     item => item.SelectedPath.FirstSegment is NavigationPropertySegment));

            Assert.Equal(
                "Parent",
                ((NavigationPropertySegment)parentSelectItem.SelectedPath.FirstSegment).NavigationProperty.Name);

            expandedItem = Assert.Single(clause.SelectedItems.OfType <ExpandedNavigationSelectItem>());
            Assert.Equal(
                "Parent",
                ((NavigationPropertySegment)expandedItem.PathToNavigationProperty.FirstSegment).NavigationProperty.Name);
            Assert.Null(expandedItem.LevelsOption);

            clause = expandedItem.SelectAndExpand;
            Assert.False(clause.AllSelected);
            Assert.Single(clause.SelectedItems);

            idSelectItem = Assert.IsType <PathSelectItem>(clause.SelectedItems.Single());
            Assert.Equal("ID", ((PropertySegment)idSelectItem.SelectedPath.FirstSegment).Property.Name);
        }
コード例 #21
0
 public static bool IsValid(SelectExpandQueryOption selectExpandQueryOption)
 {
     return(selectExpandQueryOption?.SelectExpandClause?.SelectedItems != null);
 }
コード例 #22
0
ファイル: SelectExpandBinder.cs プロジェクト: akorchev/odata
        public SelectExpandBinder(ODataQuerySettings settings, IAssemblyProvider assembliesProvider, SelectExpandQueryOption selectExpandQuery)
        {
            Contract.Assert(settings != null);
            Contract.Assert(assembliesProvider != null);
            Contract.Assert(selectExpandQuery != null);
            Contract.Assert(selectExpandQuery.Context != null);
            Contract.Assert(selectExpandQuery.Context.Model != null);
            Contract.Assert(settings.HandleNullPropagation != HandleNullPropagationOption.Default);

            _selectExpandQuery = selectExpandQuery;
            _context           = selectExpandQuery.Context;
            _model             = _context.Model;
            _modelID           = ModelContainer.GetModelID(_model);
            _settings          = settings;
            _assemblyProvider  = assembliesProvider;
        }
コード例 #23
0
        public void ProcessLevelsCorrectly_NotAllSelected()
        {
            // Arrange
            var model   = ODataLevelsTest.GetEdmModel();
            var context = new ODataQueryContext(
                model,
                model.FindDeclaredType("Microsoft.AspNet.OData.Test.Routing.LevelsEntity"));

            context.RequestContainer = new MockContainer();
            var selectExpand = new SelectExpandQueryOption(
                select: "Name",
                expand: "Parent($select=ID;$levels=max)",
                context: context);

            // Act
            SelectExpandClause clause = selectExpand.ProcessLevels();

            // Assert
            // Level 1.
            Assert.False(clause.AllSelected);
            Assert.Equal(3, clause.SelectedItems.Count());

            var nameSelectItem = Assert.Single(clause.SelectedItems.OfType <PathSelectItem>().Where(
                                                   item => item.SelectedPath.FirstSegment is PropertySegment));

            Assert.Equal("Name", ((PropertySegment)nameSelectItem.SelectedPath.FirstSegment).Property.Name);

            var parentSelectItem = Assert.Single(clause.SelectedItems.OfType <PathSelectItem>().Where(
                                                     item => item.SelectedPath.FirstSegment is NavigationPropertySegment));

            Assert.Equal(
                "Parent",
                ((NavigationPropertySegment)parentSelectItem.SelectedPath.FirstSegment).NavigationProperty.Name);

            var expandedItem = Assert.Single(clause.SelectedItems.OfType <ExpandedNavigationSelectItem>());

            Assert.Equal(
                "Parent",
                ((NavigationPropertySegment)expandedItem.PathToNavigationProperty.FirstSegment).NavigationProperty.Name);
            Assert.Null(expandedItem.LevelsOption);

            // Level 2.
            clause = expandedItem.SelectAndExpand;
            Assert.False(clause.AllSelected);
            Assert.Equal(3, clause.SelectedItems.Count());

            var idSelectItem = Assert.Single(clause.SelectedItems.OfType <PathSelectItem>().Where(
                                                 item => item.SelectedPath.FirstSegment is PropertySegment));

            Assert.Equal("ID", ((PropertySegment)idSelectItem.SelectedPath.FirstSegment).Property.Name);

            parentSelectItem = Assert.Single(clause.SelectedItems.OfType <PathSelectItem>().Where(
                                                 item => item.SelectedPath.FirstSegment is NavigationPropertySegment));
            Assert.Equal(
                "Parent",
                ((NavigationPropertySegment)parentSelectItem.SelectedPath.FirstSegment).NavigationProperty.Name);

            expandedItem = Assert.Single(clause.SelectedItems.OfType <ExpandedNavigationSelectItem>());
            Assert.Equal(
                "Parent",
                ((NavigationPropertySegment)expandedItem.PathToNavigationProperty.FirstSegment).NavigationProperty.Name);
            Assert.Null(expandedItem.LevelsOption);

            clause = expandedItem.SelectAndExpand;
            Assert.False(clause.AllSelected);
            Assert.Single(clause.SelectedItems);

            idSelectItem = Assert.IsType <PathSelectItem>(clause.SelectedItems.Single());
            Assert.Equal("ID", ((PropertySegment)idSelectItem.SelectedPath.FirstSegment).Property.Name);
        }
コード例 #24
0
        public async Task <IActionResult> OData(ODataQueryOptions <DeveloperDto> oDataQuery)
        {
            var edmModel     = EdmModelConfig.GetEdmModel();
            var edmEntitySet = edmModel.FindDeclaredEntitySet(nameof(Developer));

            var context = new ODataQueryContext(edmModel, typeof(Developer), oDataQuery.Context.Path);
            var edmType = context.ElementType;

            var parameters = new Dictionary <string, string>();

            if (!string.IsNullOrWhiteSpace(oDataQuery.RawValues.Filter))
            {
                parameters.Add("$filter", oDataQuery.RawValues.Filter);
            }

            if (!string.IsNullOrWhiteSpace(oDataQuery.RawValues.Expand))
            {
                parameters.Add("$expand", oDataQuery.RawValues.Expand);
            }

            if (!string.IsNullOrWhiteSpace(oDataQuery.RawValues.OrderBy))
            {
                parameters.Add("$orderby", oDataQuery.RawValues.OrderBy);
            }

            var parser = new ODataQueryOptionParser(edmModel, edmType, edmEntitySet, parameters);

            var queryable = (IQueryable <Developer>)_databaseContext.Developer;

            if (!string.IsNullOrWhiteSpace(oDataQuery.RawValues.Filter))
            {
                var filter = new FilterQueryOption(oDataQuery.RawValues.Filter, context, parser);
                queryable = (IQueryable <Developer>)filter.ApplyTo(queryable, new ODataQuerySettings());
            }

            if (!string.IsNullOrWhiteSpace(oDataQuery.RawValues.OrderBy))
            {
                var orderBy = new OrderByQueryOption(oDataQuery.RawValues.OrderBy, context, parser);
                queryable = orderBy.ApplyTo(queryable, new ODataQuerySettings());
            }

            IQueryable <object> expandableQueryable = null;

            if (!string.IsNullOrWhiteSpace(oDataQuery.RawValues.Expand))
            {
                var expand = new SelectExpandQueryOption(null, oDataQuery.RawValues.Expand, context, parser);
                expandableQueryable = (IQueryable <object>)expand.ApplyTo(queryable, new ODataQuerySettings());
            }

            int pageIndex    = 1;
            var hasPageIndex = oDataQuery.Request.Query.TryGetValue("$pageindex", out StringValues pageIndexRaw);

            if (hasPageIndex)
            {
                var isTrue = int.TryParse(pageIndexRaw, out int _pageIndexRaw);
                pageIndex = (isTrue && _pageIndexRaw > 0) ? _pageIndexRaw : pageIndex;
            }

            int pageSize    = 10;
            var hasPageSize = oDataQuery.Request.Query.TryGetValue("$pagesize", out StringValues pageSizeRaw);

            if (hasPageSize)
            {
                var isTrue = int.TryParse(pageSizeRaw, out int _pageSizeRaw);
                pageSize = (isTrue && _pageSizeRaw > 0) ? _pageSizeRaw : pageSize;
            }

            IQueryable <object> queryToExecute = expandableQueryable ?? queryable;
            var records = await queryToExecute.Skip((pageIndex - 1) *pageSize).Take(pageSize).ToListAsync();

            var count = await queryToExecute.CountAsync();

            var pageList = new PageList <Developer>(MapDomain(records).ToList(), count, pageIndex, pageSize);
            var response = PageListDto <DeveloperDto> .Map(pageList, DeveloperDto.MapDomainToDto);

            return(Ok(response));
        }
コード例 #25
0
        public void Validate_Throw_WithInvalidMaxExpansionDepth()
        {
            int maxExpansionDepth = -1;
            // Arrange
            string expand = "Parent($levels=1)";
            var validator = new SelectExpandQueryValidator();
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<ODataLevelsTest.LevelsEntity>("Entities");
            IEdmModel model = builder.GetEdmModel();
            var context = new ODataQueryContext(model, typeof(ODataLevelsTest.LevelsEntity));
            var selectExpandQueryOption = new SelectExpandQueryOption(null, expand, context);

            // Act & Assert
            Assert.Throws<ArgumentOutOfRangeException>(
                () => validator.Validate(
                    selectExpandQueryOption,
                    new ODataValidationSettings { MaxExpansionDepth = maxExpansionDepth }),
                "Value must be greater than or equal to 0.\r\nParameter name: value\r\nActual value was -1.");
        }
コード例 #26
0
        public void ValidateDoesNotThrow_IfExpansionDepthIsZero_DollarLevels()
        {
            // Arrange
            string expand = "Parent($expand=Parent($expand=Parent($levels=10)))";
            var validator = new SelectExpandQueryValidator();
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<ODataLevelsTest.LevelsEntity>("Entities");
            IEdmModel model = builder.GetEdmModel();
            var context = new ODataQueryContext(model, typeof(ODataLevelsTest.LevelsEntity));
            var selectExpandQueryOption = new SelectExpandQueryOption(null, expand, context);

            // Act & Assert
            Assert.DoesNotThrow(
                () => validator.Validate(
                    selectExpandQueryOption,
                    new ODataValidationSettings { MaxExpansionDepth = 0 }));
        }
コード例 #27
0
        public void ValidateDoesNotThrow_LevelsMaxLiteralExpansionDepthAndMaxExpansionDepth(
            int levelsMaxLiteralExpansionDepth,
            int maxExpansionDepth)
        {
            // Arrange
            string expand = "Parent($levels=2)";
            var validator = new SelectExpandQueryValidator();
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<ODataLevelsTest.LevelsEntity>("Entities");
            IEdmModel model = builder.GetEdmModel();
            var context = new ODataQueryContext(model, typeof(ODataLevelsTest.LevelsEntity));
            var selectExpandQueryOption = new SelectExpandQueryOption(null, expand, context);
            selectExpandQueryOption.LevelsMaxLiteralExpansionDepth = levelsMaxLiteralExpansionDepth;

            // Act & Assert
            Assert.DoesNotThrow(
                () => validator.Validate(
                    selectExpandQueryOption,
                    new ODataValidationSettings { MaxExpansionDepth = maxExpansionDepth }));
        }
コード例 #28
0
        public static IQueryable Bind(IQueryable queryable, ODataQuerySettings settings, SelectExpandQueryOption selectExpandQuery)
        {
            Contract.Assert(queryable != null);

            SelectExpandBinder binder = new SelectExpandBinder(settings, selectExpandQuery);

            return(binder.Bind(queryable));
        }
        /// <summary>
        /// Resolves the @odata.context URI for the specified request and Entity Set and select query option.
        /// </summary>
        /// <param name="request">The HTTP request message which led to this OData request.</param>
        /// <param name="entitySet">The EntitySet used in the request.</param>
        /// <param name="selectExpandQueryOption">The select query option.</param>
        /// <returns>A <see cref="Uri"/> containing the @odata.context URI, or null if the metadata for the request is none.</returns>
        public static Uri ResolveODataContextUri(this HttpRequestMessage request, EntitySet entitySet, SelectExpandQueryOption selectExpandQueryOption)
        {
            var requestOptions = request.ReadODataRequestOptions();

            if (requestOptions.MetadataLevel == ODataMetadataLevel.None)
            {
                return(null);
            }

            return(new Uri(request.RequestUri.ODataContextUriBuilder(entitySet, selectExpandQueryOption).ToString()));
        }
コード例 #30
0
 public static ICollection <string> GetExpandedFields(this SelectExpandQueryOption selectExpandQueryOption)
 {
     return(GetExpandedFields(selectExpandQueryOption.SelectExpandClause.SelectedItems));
 }
コード例 #31
0
        internal static StringBuilder ODataContextUriBuilder(this Uri requestUri, EntitySet entitySet, SelectExpandQueryOption selectExpandQueryOption)
        {
            var contextUriBuilder = ODataContextUriBuilder(requestUri);

            contextUriBuilder.Append("#").Append(entitySet.Name);

            if (selectExpandQueryOption?.RawValue.Equals("$select=*") == true)
            {
                contextUriBuilder.Append("(*)");
            }
            else if (selectExpandQueryOption?.Properties.Count > 0)
            {
                contextUriBuilder.AppendFormat("({0})", string.Join(",", selectExpandQueryOption.Properties));
            }

            return(contextUriBuilder);
        }
コード例 #32
0
        public void Bind_GeneratedExpression_CheckNullObjectWithinChainProjectionByKey()
        {
            // Arrange
            SelectExpandQueryOption selectExpand = new SelectExpandQueryOption(null, "Orders($expand=Customer($select=City))", _context);
            _model.Model.SetAnnotationValue(_model.Order, new DynamicPropertyDictionaryAnnotation(typeof(Order).GetProperty("OrderProperties")));

            // Act
            IQueryable queryable = SelectExpandBinder.Bind(_queryable, _settings, new DefaultAssembliesResolver(), selectExpand);

            // Assert
            var unaryExpression = (UnaryExpression)((MethodCallExpression)queryable.Expression).Arguments.Single(a => a is UnaryExpression);
            var expressionString = unaryExpression.Operand.ToString();
            Assert.Contains("IsNull = (Convert(Param_1.Customer.ID) == null)", expressionString);
        }