// Pass ODataQueryOptions as parameter, and call validation manually
        public IHttpActionResult GetFromManager(ODataQueryOptions<Manager> queryOptions)
        {
            if (queryOptions.SelectExpand != null)
            {
                queryOptions.SelectExpand.LevelsMaxLiteralExpansionDepth = 5;
            }

            var validationSettings = new ODataValidationSettings { MaxExpansionDepth = 5 };

            try
            {
                queryOptions.Validate(validationSettings);
            }
            catch (ODataException e)
            {
                var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest);
                responseMessage.Content = new StringContent(
                    string.Format("The query specified in the URI is not valid. {0}", e.Message));
                return ResponseMessage(responseMessage);
            }

            var querySettings = new ODataQuerySettings();
            var result = queryOptions.ApplyTo(_employees.OfType<Manager>().AsQueryable(), querySettings).AsQueryable();
            return Ok(result, result.GetType());
        }
Exemple #2
0
        public static ODataQueryOptions CreateValidQueryOptions(IEdmModel model, Type elementClrType, HttpRequestMessage request, ODataValidationSettings validationSettings)
        {
            var queryOptions = CreateQueryOptions(model, elementClrType, request);

            queryOptions.Validate(validationSettings);

            return queryOptions;
        }
 // Disallow the 'desc' parameter for $orderby option.
 public override void Validate(OrderByQueryOption orderByOption,
                                 ODataValidationSettings validationSettings)
 {
     if (orderByOption.OrderByNodes.Any(
             node => node.Direction == OrderByDirection.Descending))
     {
         throw new ODataException("The 'desc' option is not supported.");
     }
     base.Validate(orderByOption, validationSettings);
 }
            public override void ValidateSingleValuePropertyAccessNode(SingleValuePropertyAccessNode propertyAccessNode, ODataValidationSettings settings)
            {
                // Validate if we are accessing some sensitive property of Order, such as Quantity
                if (propertyAccessNode.Property.Name == "Quantity")
                {
                    throw new ODataException("Filter with Quantity is not allowed.");
                }

                base.ValidateSingleValuePropertyAccessNode(propertyAccessNode, settings);
            }
        public void AllowedOrderByProperties_Property_RoundTrips()
        {
            ODataValidationSettings settings = new ODataValidationSettings();
            Assert.NotNull(settings.AllowedOrderByProperties);
            Assert.Equal(0, settings.AllowedOrderByProperties.Count);

            settings.AllowedOrderByProperties.Add("Id");
            settings.AllowedOrderByProperties.Add("Name");

            Assert.Equal(2, settings.AllowedOrderByProperties.Count);
            Assert.Equal("Id", settings.AllowedOrderByProperties[0]);
            Assert.Equal("Name", settings.AllowedOrderByProperties[1]);
        }
        public void Ctor_Initializes_All_Properties()
        {
            // Arrange & Act
            ODataValidationSettings querySettings = new ODataValidationSettings();

            // Assert
            Assert.Equal(AllowedArithmeticOperators.All, querySettings.AllowedArithmeticOperators);
            Assert.Equal(AllowedFunctions.AllFunctions, querySettings.AllowedFunctions);
            Assert.Equal(AllowedLogicalOperators.All, querySettings.AllowedLogicalOperators);
            Assert.Equal(0, querySettings.AllowedOrderByProperties.Count);
            Assert.Equal(AllowedQueryOptions.Supported, querySettings.AllowedQueryOptions);
            Assert.Equal(1, querySettings.MaxAnyAllExpressionDepth);
            Assert.Equal(100, querySettings.MaxNodeCount);
            Assert.Null(querySettings.MaxSkip);
            Assert.Null(querySettings.MaxTop);
        }
        // Note this can be done through Queryable attribute as well
        public IQueryable<Order> Get(ODataQueryOptions queryOptions)
        {
            // Register a custom FilterByValidator to disallow custom logic in the filter query
            if (queryOptions.Filter != null)
            {
                queryOptions.Filter.Validator = new RestrictiveFilterByQueryValidator();
            }

            // Validate the query, we only allow order by Id property and
            // we only allow maximum Top query value to be 9
            ODataValidationSettings settings = new ODataValidationSettings() { MaxTop = 9 };
            settings.AllowedOrderByProperties.Add("Id");
            queryOptions.Validate(settings);

            // Apply the query
            return queryOptions.ApplyTo(OrderList.AsQueryable()) as IQueryable<Order>;
        }
        public IHttpActionResult Get(ODataQueryOptions<DLManager> queryOptions)
        {
            ODataValidationSettings settings = new ODataValidationSettings();
            settings.MaxExpansionDepth = 1;

            try
            {
                queryOptions.Validate(settings);
            }
            catch (ODataException e)
            {
                var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest);
                responseMessage.Content = new StringContent(
                    String.Format("The query specified in the URI is not valid. {0}", e.Message));
                return ResponseMessage(responseMessage);
            }

            var managers = queryOptions.ApplyTo(_DLManagers.AsQueryable()).AsQueryable();
            return Ok(managers, managers.GetType());
        }
        /// <inheritdoc />
        public override void Validate(ODataQueryOptions options, ODataValidationSettings validationSettings)
        {
            base.Validate(options, validationSettings);

            if (options.SelectExpand == null)
            {
                // Nothing to validate.
                return;
            }

            // We only validate the $expand operator, so a different mechanism is required to restrict access to a
            // navigation source directly. For example, we restrict $expand=Orders, but we don't restrict accessing
            // orders through /Orders. The recommendation for restricting access to a navigation source in the URL path
            // is to use an IAuthorizationFilter.
            SelectExpandClause selectExpandClause = options.SelectExpand.SelectExpandClause;
            IList<ExpandedNavigationSelectItem> expandedItems = GetExpandedProperties(selectExpandClause);
            foreach (ExpandedNavigationSelectItem item in expandedItems)
            {
                ValidateExpandedItem(item);
            }
        }
        public void CanTurnOffAllValidation()
        {
            // Arrange
            HttpRequestMessage message = new HttpRequestMessage(
                HttpMethod.Get,
                new Uri("http://localhost/?$filter=Name eq 'abc'")
            );

            ODataQueryContext context = ValidationTestHelper.CreateCustomerContext();
            ODataQueryOptions option = new ODataQueryOptions(context, message);
            ODataValidationSettings settings = new ODataValidationSettings()
            {
                AllowedQueryOptions = AllowedQueryOptions.OrderBy
            };

            // Act & Assert
            Assert.Throws<ODataException>(() => option.Validate(settings),
                "Query option 'Filter' is not allowed. To allow it, set the 'AllowedQueryOptions' property on EnableQueryAttribute or QueryValidationSettings.");

            option.Validator = null;
            Assert.DoesNotThrow(() => option.Validate(settings));

        }
        public void Validate_ThrowsValidationErrors_ForOrderBy()
        {
            // Arrange
            var model = new ODataModelBuilder().Add_Customer_EntityType().GetEdmModel();

            var message = new HttpRequestMessage(
                HttpMethod.Get,
                new Uri("http://server/service/Customers?$orderby=CustomerId,Name")
            );

            var options = new ODataQueryOptions(new ODataQueryContext(model, typeof(Customer)), message);
            ODataValidationSettings validationSettings = new ODataValidationSettings { MaxOrderByNodeCount = 1 };

            // Act & Assert
            Assert.Throws<ODataException>(() => options.Validate(validationSettings),
                "The number of clauses in $orderby query option exceeded the maximum number allowed. The maximum number of $orderby clauses allowed is 1.");
        }
 public void VerifyValidateOptions(ODataValidationSettings settings, string query, bool success)
 {
     var response = this.Client.PostAsync(
         this.BaseAddress + "/api/ValidatorTests/ValidateOptions?" + query,
         new ObjectContent<ODataValidationSettings>(settings, new JsonMediaTypeFormatter())).Result;
     if (success)
     {
         response.EnsureSuccessStatusCode();
     }
     else
     {
         Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
     }
 }
        public void CanTurnOffValidationForOrderBy()
        {
            // Arrange
            ODataQueryContext context = ValidationTestHelper.CreateCustomerContext();

            OrderByQueryOption option = new OrderByQueryOption("Name", context);
            ODataValidationSettings settings = new ODataValidationSettings();
            settings.AllowedOrderByProperties.Add("Id");

            // Act & Assert
            Assert.Throws<ODataException>(() => option.Validate(settings),
                "Order by 'Name' is not allowed. To allow it, set the 'AllowedOrderByProperties' property on EnableQueryAttribute or QueryValidationSettings.");

            option.Validator = null;
            Assert.DoesNotThrow(() => option.Validate(settings));
        }
        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 EnableQueryAttribute or QueryValidationSettings.");

            option.Validator = null;
            Assert.DoesNotThrow(() => option.Validate(settings));
        }
        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));
        }
 public IQueryable<ValidatorTests_Todo> ValidateWithCustomValidator(ODataQueryOptions options)
 {
     if (options.Filter != null)
     {
         options.Filter.Validator = new CustomFilterValidator();
     }
     try
     {
         ODataValidationSettings settings = new ODataValidationSettings();
         options.Validate(settings);
     }
     catch (ODataException ex)
     {
         throw new HttpResponseException(this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex));
     }
     return options.ApplyTo(todoes.AsQueryable()) as IQueryable<ValidatorTests_Todo>;
 }
 public override void ValidateSingleValuePropertyAccessNode(Microsoft.OData.Core.UriParser.Semantic.SingleValuePropertyAccessNode propertyAccessNode, ODataValidationSettings settings)
 {
     if (propertyAccessNode.Property.Name == "ID")
     {
         visited = true;
     }
     base.ValidateSingleValuePropertyAccessNode(propertyAccessNode, settings);
 }
        /// <summary>
        /// Validate the $select and $expand query based on the given <paramref name="validationSettings"/>. It throws an ODataException if validation failed.
        /// </summary>
        /// <param name="validationSettings">The <see cref="ODataValidationSettings"/> instance which contains all the validation settings.</param>
        public void Validate(ODataValidationSettings validationSettings)
        {
            if (validationSettings == null)
            {
                throw Error.ArgumentNull("validationSettings");
            }

            if (Validator != null)
            {
                Validator.Validate(this, validationSettings);
            }
        }
            public IHttpActionResult Get(ODataQueryOptions<LevelsEntity> queryOptions)
            {
                var validationSettings = new ODataValidationSettings { MaxExpansionDepth = 5 };

                try
                {
                    queryOptions.Validate(validationSettings);
                }
                catch (ODataException e)
                {
                    var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest);
                    responseMessage.Content = new StringContent(
                        Error.Format("The query specified in the URI is not valid. {0}", e.Message));
                    return ResponseMessage(responseMessage);
                }

                var querySettings = new ODataQuerySettings();
                var result = queryOptions.ApplyTo(Entities.AsQueryable(), querySettings).AsQueryable();
                return Ok(result, result.GetType());
            }
        public IHttpActionResult Get(int key, ODataQueryOptions<Employee> options)
        {
            if (options.SelectExpand != null)
            {
                options.SelectExpand.LevelsMaxLiteralExpansionDepth = 3;
            }

            var validationSettings = new ODataValidationSettings { MaxExpansionDepth = 3 };

            try
            {
                options.Validate(validationSettings);
            }
            catch (ODataException e)
            {
                HttpResponseMessage resoponse = Request.CreateErrorResponse(HttpStatusCode.BadRequest, e.Message, e);
                return ResponseMessage(resoponse);
            }

            var querySettings = new ODataQuerySettings();
            Employee employee = _employees.Single(e => e.ID == key);
            var result = options.ApplyTo(employee, new ODataQuerySettings());
            Type type = result.GetType();
            return Ok(result, type);

        }
        public override void Validate(FilterQueryOption filterQueryOption, ODataValidationSettings settings)
        {
            base.Validate(filterQueryOption, settings);

            if (!visited)
            {
                throw new ODataException("$filter query must contain ID property");
            }
        }
        public IHttpActionResult Get(int key, ODataQueryOptions<DLEmployee> queryOptions)
        {
            ODataValidationSettings settings = new ODataValidationSettings();
            settings.MaxExpansionDepth = 3;

            try
            {
                queryOptions.Validate(settings);
            }
            catch (ODataException e)
            {
                var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest);
                responseMessage.Content = new StringContent(
                    String.Format("The query specified in the URI is not valid. {0}", e.Message));
                return ResponseMessage(responseMessage);
            }

            var employee = _DLEmployees.Single(e=>e.ID == key);
            var appliedEmployee = queryOptions.ApplyTo(employee, new ODataQuerySettings());
            return Ok(appliedEmployee, appliedEmployee.GetType());
        }
 /// <summary>
 /// Enables a controller action to support OData query parameters.
 /// </summary>
 public EnableQueryAttribute()
 {
     _validationSettings = new ODataValidationSettings();
     _querySettings = new ODataQuerySettings();
 }
        public IHttpActionResult Get(ODataQueryOptions<DLEmployee> queryOptions)
        {
            if (queryOptions.SelectExpand != null)
            {
                queryOptions.SelectExpand.LevelsMaxLiteralExpansionDepth = 2;
            }

            ODataValidationSettings settings = new ODataValidationSettings();
            settings.MaxExpansionDepth = 4;

            try
            {
                queryOptions.Validate(settings);
            }
            catch (ODataException e)
            {
                var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest);
                responseMessage.Content = new StringContent(
                    String.Format("The query specified in the URI is not valid. {0}", e.Message));
                return ResponseMessage(responseMessage);
            }

            var employees = queryOptions.ApplyTo(_DLEmployees.AsQueryable()).AsQueryable();
            return Ok(employees, employees.GetType());
        }
Exemple #25
-1
        public IQueryable<Team> GetTeams(ODataQueryOptions queryOptions)
        {
            // Validate query options
            var settings = new ODataValidationSettings()
            {
                MaxTop = 400
            };
            queryOptions.Validate(settings);

            // Apply the filter before going through to check if links exist for significant performance improvements
            var teams = (IQueryable<Team>)queryOptions.ApplyTo(Db.core.Teams);

            // RouteLinker creates Uris for actions
            var linker = new RouteLinker(Request);

            foreach (var team in teams)
            {
                if (team.Links == null)
                {
                    team.Links = new SerializableDynamic();
                    team.Links.url = linker.GetUri<TeamsController>(c => c.GetTeam(team.Number)).ToString();
                }
            }

            var nextRequest = Request.RequestUri;

            return Db.core.Teams.AsQueryable();
        }