/// <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 Value_Returns_ParsedSkipValue(string skipValue, int expectedValue)
        {
            var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel();
            var context = new ODataQueryContext(model, typeof(Customer));
            var skip = new SkipQueryOption(skipValue, context);

            Assert.Equal(expectedValue, skip.Value);
        }
        public void CanConstructValidFilterQuery(string skipValue)
        {
            var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel();
            var context = new ODataQueryContext(model, typeof(Customer));
            var skip = new SkipQueryOption(skipValue, context);

            Assert.Same(context, skip.Context);
            Assert.Equal(skipValue, skip.RawValue);
        }
        public void ApplyInValidSkipQueryThrows(string skipValue)
        {
            var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel();
            var context = new ODataQueryContext(model, typeof(Customer));
            var skip = new SkipQueryOption(skipValue, context);

            Assert.Throws<ODataException>(() =>
                skip.ApplyTo(ODataQueryOptionTest.Customers));
        }
        private static IQuery Apply(this IQuery query, SkipQueryOption skipQuery)
        {
            if (skipQuery != null)
            {
                query = query.SetFirstResult(skipQuery.Value);
            }

            return query;
        }
        public void ApplyTo_WithUnTypedContext_Throws_InvalidOperation()
        {
            // Arrange
            CustomersModelWithInheritance model = new CustomersModelWithInheritance();
            ODataQueryContext context = new ODataQueryContext(model.Model, model.Customer);
            SkipQueryOption skip = new SkipQueryOption("42", context);
            IQueryable queryable = new Mock<IQueryable>().Object;

            // Act & Assert
            Assert.Throws<NotSupportedException>(() => skip.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.");
        }
Exemple #7
0
        public static HttpRequestMessage BuildCustomRequest(this ODataQueryOptions originalOptions,
            out TopQueryOption top,
            out SkipQueryOption skip, out OrderByQueryOption orderBy)
        {
            top = null;
            skip = null;
            orderBy = null;

            // cuttin out $top and $skip from the request
            HttpRequestMessage customRequest = originalOptions.Request;

            if (customRequest.Properties.ContainsKey(HttpPropertyKeys.RequestQueryNameValuePairsKey))
            {
                Uri uri = originalOptions.Request.RequestUri;
                var pairs =
                    customRequest.Properties[HttpPropertyKeys.RequestQueryNameValuePairsKey] as
                        IEnumerable<KeyValuePair<string, string>>;

                if (pairs != null)
                {
                    IEnumerable<KeyValuePair<string, string>> jQueryNameValuePairs =
                        new FormDataCollection(uri).GetJQueryNameValuePairs();
                    var updatedPairs = new List<KeyValuePair<string, string>>();

                    foreach (var pair in jQueryNameValuePairs)
                    {
                        if (pair.Key.Equals("$top"))
                        {
                            top = originalOptions.Top;
                        }
                        else if (pair.Key.Equals("$skip"))
                        {
                            skip = originalOptions.Skip;
                        }
                        else if (pair.Key.Equals("$orderby"))
                        {
                            orderBy = originalOptions.OrderBy;
                        }
                        else
                        {
                            updatedPairs.Add(pair);
                        }
                    }

                    customRequest.Properties.Remove(HttpPropertyKeys.RequestQueryNameValuePairsKey);
                    customRequest.Properties.Add(HttpPropertyKeys.RequestQueryNameValuePairsKey, updatedPairs);
                }
            }

            return customRequest;
        }
        public void CanApplySkip()
        {
            var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetServiceModel();
            var skipOption = new SkipQueryOption("1", new ODataQueryContext(model, typeof(Customer), "Customers"));

            var customers = (new List<Customer>{
                new Customer { CustomerId = 1, Name = "Andy" },
                new Customer { CustomerId = 2, Name = "Aaron" },
                new Customer { CustomerId = 3, Name = "Alex" }
            }).AsQueryable();

            var results = skipOption.ApplyTo(customers).ToArray();
            Assert.Equal(2, results.Length);
            Assert.Equal(2, results[0].CustomerId);
            Assert.Equal(3, results[1].CustomerId);
        }
        /// <summary>
        /// Validates a <see cref="SkipQueryOption" />.
        /// </summary>
        /// <param name="skipQueryOption">The $skip query.</param>
        /// <param name="validationSettings">The validation settings.</param>
        public virtual void Validate(SkipQueryOption skipQueryOption, ODataValidationSettings validationSettings)
        {
            if (skipQueryOption == null)
            {
                throw Error.ArgumentNull("skipQueryOption");
            }

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

            if (skipQueryOption.Value > validationSettings.MaxSkip)
            {
                throw new ODataException(Error.Format(SRResources.SkipTopLimitExceeded, validationSettings.MaxSkip, AllowedQueryOptions.Skip, skipQueryOption.Value));
            }
        }
        /// <summary>
        /// Validates a <see cref="SkipQueryOption" />.
        /// </summary>
        /// <param name="skipQueryOption">The $skip query.</param>
        /// <param name="validationSettings">The validation settings.</param>
        public virtual void Validate(SkipQueryOption skipQueryOption, ODataValidationSettings validationSettings)
        {
            if (skipQueryOption == null)
            {
                throw Error.ArgumentNull("skipQueryOption");
            }

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

            if (skipQueryOption.Value > validationSettings.MaxSkip)
            {
                throw new ODataException(Error.Format(SRResources.SkipTopLimitExceeded, validationSettings.MaxSkip, AllowedQueryOptions.Skip, skipQueryOption.Value));
            }
        }
        public void CanApplySkipOrderby()
        {
            var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetServiceModel();
            var context = new ODataQueryContext(model, typeof(Customer));
            var orderbyOption = new OrderByQueryOption("Name", context, queryTranslator: null);
            var skipOption = new SkipQueryOption("1", context);

            var customers = (new List<Customer>{
                new Customer { CustomerId = 1, Name = "Andy" },
                new Customer { CustomerId = 2, Name = "Aaron" },
                new Customer { CustomerId = 3, Name = "Alex" }
            }).AsQueryable();

            IQueryable queryable = orderbyOption.ApplyTo(customers);
            queryable = skipOption.ApplyTo(queryable, new ODataQuerySettings());
            var results = ((IQueryable<Customer>)queryable).ToArray();
            Assert.Equal(2, results.Length);
            Assert.Equal(3, results[0].CustomerId);
            Assert.Equal(1, results[1].CustomerId);
        }
Exemple #12
0
        public void CanApplySkipTopOrderby()
        {
            var model   = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetServiceModel();
            var context = new ODataQueryContext(model, typeof(Customer))
            {
                RequestContainer = new MockContainer()
            };
            var orderbyOption = new OrderByQueryOption("Name", context);
            var skipOption    = new SkipQueryOption("2", context);
            var topOption     = new TopQueryOption("2", context);

            var customers = (new List <Customer> {
                new Customer {
                    CustomerId = 1, Name = "Andy"
                },
                new Customer {
                    CustomerId = 2, Name = "Aaron"
                },
                new Customer {
                    CustomerId = 3, Name = "Alex"
                },
                new Customer {
                    CustomerId = 4, Name = "Ace"
                },
                new Customer {
                    CustomerId = 5, Name = "Abner"
                }
            }).AsQueryable();

            IQueryable queryable = orderbyOption.ApplyTo(customers);

            queryable = skipOption.ApplyTo(queryable, new ODataQuerySettings());
            queryable = topOption.ApplyTo(queryable, new ODataQuerySettings());
            var results = ((IQueryable <Customer>)queryable).ToArray();

            Assert.Equal(2, results.Length);
            Assert.Equal(4, results[0].CustomerId);
            Assert.Equal(3, results[1].CustomerId);
        }
Exemple #13
0
        public void CanApplySkip()
        {
            var model      = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel();
            var skipOption = new SkipQueryOption("1", new ODataQueryContext(model, typeof(Customer)));

            var customers = (new List <Customer> {
                new Customer {
                    Id = 1, Name = "Andy"
                },
                new Customer {
                    Id = 2, Name = "Aaron"
                },
                new Customer {
                    Id = 3, Name = "Alex"
                }
            }).AsQueryable();

            var results = skipOption.ApplyTo(customers, new ODataQuerySettings()).ToArray();

            Assert.Equal(2, results.Length);
            Assert.Equal(2, results[0].Id);
            Assert.Equal(3, results[1].Id);
        }
Exemple #14
0
        /// <summary>
        /// Updates the QueryExpression's paging settings based on OData parameters.
        /// </summary>
        /// <param name="pagingInfo">The target PagingInfo</param>
        /// <param name="skip">The OData options that describe how many records to skip.</param>
        /// <param name="top">The OData options that describe how many records per page.</param>
        private static void UpdatePagingFromSkipAndTop(PagingInfo pagingInfo, SkipQueryOption skip, TopQueryOption top)
        {
            if (top == null)
            {
                pagingInfo.Count = 50;
            }
            else
            {
                pagingInfo.Count = top.Value;
            }

            if (skip == null)
            {
                pagingInfo.PageNumber = 1;
            }
            else
            {
                // When syncing for offline, the client will always request a page immediately after
                // the last record.  So if there are only 7 records, it will request with $top=50 and
                // $skip=7.  To handle these cases when $skip is not evenly divisible by $top, we round
                // up, which will send back an empty result set on the last page and complete the sync.
                pagingInfo.PageNumber = (int)Math.Ceiling((double)skip.Value / pagingInfo.Count) + 1;
            }
        }
        public void Property_Value_WorksWithUnTypedContext()
        {
            // Arrange
            CustomersModelWithInheritance model = new CustomersModelWithInheritance();
            ODataQueryContext context = new ODataQueryContext(model.Model, model.Customer);
            SkipQueryOption skip = new SkipQueryOption("42", context);

            // Act & Assert
            Assert.Equal(42, skip.Value);
        }
        public void Value_ThrowsODataException_ForInvalidValues(string skipValue)
        {
            var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel();
            var context = new ODataQueryContext(model, typeof(Customer));
            var skip = new SkipQueryOption(skipValue, context);

            Assert.Throws<ODataException>(() => skip.Value);
        }
Exemple #17
0
        private Task <IEnumerable <PackageName> > Query(FeedPrincipal principal, string packageNamePrefix, SkipQueryOption skip, TopQueryOption top)
        {
            var feed = storage.GetFeed(principal.FeedName);

            switch (principal.AuthenticatedArea)
            {
            case AuthenticatedArea.QueryingOwn:
                return(skip != null && top != null
                        ? feed.QueryPackages(principal.Identity.Name, principal.PackageState, packageNamePrefix, skip.Value, top.Value)
                        : feed.QueryPackages(principal.Identity.Name, principal.PackageState));

            case AuthenticatedArea.QueryingAll:
                return(skip != null && top != null
                        ? feed.QueryPackages(principal.PackageState, packageNamePrefix, skip.Value, top.Value)
                        : feed.QueryPackages(principal.PackageState));

            default:
                throw new ArgumentOutOfRangeException("area", principal.AuthenticatedArea, null);
            }
        }
        public void CanTurnOffValidationForSkip()
        {
            // Arrange
            ODataValidationSettings settings = new ODataValidationSettings()
            {
                MaxSkip = 10
            };
            SkipQueryOption option = new SkipQueryOption("11", ValidationTestHelper.CreateCustomerContext());

            // Act and Assert
            Assert.Throws<ODataException>(() =>
                option.Validate(settings),
                "The limit of '10' for Skip query has been exceeded. The value from the incoming request is '11'.");
            option.Validator = null;
            Assert.DoesNotThrow(() => option.Validate(settings));
        }
        /// <summary>
        /// Builds the order clause that skips and takes a number of elements.
        /// </summary>
        /// <param name="orderByQueryOption">The order by query option.</param>
        /// <param name="topQueryOption">The top query option.</param>
        /// <param name="skipQueryOption">The skip query option.</param>
        /// <returns>
        /// Returns sorted and filtered order clause.
        /// </returns>
        private string BuildOrderClause(OrderByQueryOption orderByQueryOption, TopQueryOption topQueryOption, SkipQueryOption skipQueryOption)
        {
            string orderClause   = BuildOrderClause(orderByQueryOption);
            string skipTopClause = BuildSkipTopClause(topQueryOption, skipQueryOption);

            if (string.IsNullOrEmpty(skipTopClause))
            {
                return(orderClause);
            }

            return($"{orderClause} {skipTopClause}");
        }
 public static IAsyncEnumerable <T> ApplyTo <T>(this SkipQueryOption query, IAsyncEnumerable <T> source, ODataQuerySettings settings)
 {
     return(source.SkipAsync(query.Value));
 }