static void AppendAllowedOptions(StringBuilder description, ODataQueryOptionDescriptionContext context)
        {
            Contract.Requires(description != null);
            Contract.Requires(context != null);

            if (context.AllowedLogicalOperators != AllowedLogicalOperators.None &&
                context.AllowedLogicalOperators != AllowedLogicalOperators.All)
            {
                var operators = ToCommaSeparatedValues(EnumerateLogicalOperators(context.AllowedLogicalOperators));
                description.Append(Space);
                description.AppendFormat(CurrentCulture, SR.AllowedLogicalOperatorsDesc, operators);
            }

            if (context.AllowedArithmeticOperators != AllowedArithmeticOperators.None &&
                context.AllowedArithmeticOperators != AllowedArithmeticOperators.All)
            {
                var operators = ToCommaSeparatedValues(EnumerateArithmeticOperators(context.AllowedArithmeticOperators));
                description.Append(Space);
                description.AppendFormat(CurrentCulture, SR.AllowedArithmeticOperatorsDesc, operators);
            }

            if (context.AllowedFunctions != AllowedFunctions.None &&
                context.AllowedFunctions != AllowedFunctions.All)
            {
#pragma warning disable CA1308 // Normalize strings to uppercase
                var functions = context.AllowedFunctions.ToString().ToLowerInvariant();
#pragma warning restore CA1308

                description.Append(Space);
                description.AppendFormat(CurrentCulture, SR.AllowedFunctionsDesc, functions);
            }
        }
Example #2
0
        /// <inheritdoc />
        public virtual void ApplyTo(ApiDescription apiDescription)
        {
            Arg.NotNull(apiDescription, nameof(apiDescription));

            if (!IsSupported(apiDescription))
            {
                return;
            }

            var context      = new ODataQueryOptionDescriptionContext(ValidationSettings);
            var model        = apiDescription.EdmModel();
            var queryOptions = GetQueryOptions(Settings.DefaultQuerySettings, context);
            var singleResult = IsSingleResult(apiDescription, out var resultType);
            var visitor      = new ODataAttributeVisitor(context, model, queryOptions, resultType, singleResult);

            visitor.Visit(apiDescription);

            var options = visitor.AllowedQueryOptions;
            var parameterDescriptions = apiDescription.ParameterDescriptions;

            if (options.HasFlag(Select))
            {
                parameterDescriptions.Add(NewSelectParameter(context));
            }

            if (options.HasFlag(Expand))
            {
                parameterDescriptions.Add(NewExpandParameter(context));
            }

            if (singleResult)
            {
                return;
            }

            if (options.HasFlag(Filter))
            {
                parameterDescriptions.Add(NewFilterParameter(context));
            }

            if (options.HasFlag(OrderBy))
            {
                parameterDescriptions.Add(NewOrderByParameter(context));
            }

            if (options.HasFlag(Top))
            {
                parameterDescriptions.Add(NewTopParameter(context));
            }

            if (options.HasFlag(Skip))
            {
                parameterDescriptions.Add(NewSkipParameter(context));
            }

            if (options.HasFlag(Count))
            {
                parameterDescriptions.Add(NewCountParameter(context));
            }
        }
        /// <summary>
        /// Describes the $count query option.
        /// </summary>
        /// <param name="context">The current <see cref="ODataQueryOptionDescriptionContext">description context</see>.</param>
        /// <returns>The query option description.</returns>
        protected virtual string DescribeCount(ODataQueryOptionDescriptionContext context)
        {
            Arg.NotNull(context, nameof(context));
            Contract.Ensures(!string.IsNullOrEmpty(Contract.Result <string>()));

            return(SR.CountQueryOptionDesc);
        }
        public void describe_should_return_description_for_filter(
            int maxNodeCount,
            string[] properties,
            AllowedLogicalOperators logicalOperators,
            AllowedArithmeticOperators arithmeticOperators,
            AllowedFunctions functions,
            string expected)
        {
            // arrange
            var provider = new DefaultODataQueryOptionDescriptionProvider();
            var context  = new ODataQueryOptionDescriptionContext()
            {
                MaxNodeCount = maxNodeCount,
                AllowedArithmeticOperators = arithmeticOperators,
                AllowedLogicalOperators    = logicalOperators,
                AllowedFunctions           = functions
            };

            for (var i = 0; i < properties.Length; i++)
            {
                context.AllowedFilterProperties.Add(properties[i]);
            }

            // act
            var description = provider.Describe(Filter, context);

            // assert
            description.Should().Be(expected);
        }
        /// <summary>
        /// Describes the $filter query option.
        /// </summary>
        /// <param name="context">The current <see cref="ODataQueryOptionDescriptionContext">description context</see>.</param>
        /// <returns>The query option description.</returns>
        protected virtual string DescribeFilter(ODataQueryOptionDescriptionContext context)
        {
            Arg.NotNull(context, nameof(context));
            Contract.Ensures(!string.IsNullOrEmpty(Contract.Result <string>()));

            var description = new StringBuilder();

            description.Append(SR.FilterQueryOptionDesc);

            if (context.MaxNodeCount > 1)
            {
                description.Append(Space);
                description.AppendFormat(CurrentCulture, SR.MaxExpressionDesc, context.MaxNodeCount);
            }

            AppendAllowedOptions(description, context);

            if (context.AllowedFilterProperties.Count > 0)
            {
                var properties = ToCommaSeparatedValues(context.AllowedFilterProperties);
                description.Append(Space);
                description.AppendFormat(CurrentCulture, SR.AllowedPropertiesDesc, properties);
            }

            return(description.ToString());
        }
Example #6
0
        /// <summary>
        /// Creates and returns a new parameter descriptor for the $orderby query option.
        /// </summary>
        /// <param name="descriptionContext">The <see cref="ODataQueryOptionDescriptionContext">validation settings</see> used to create the parameter.</param>
        /// <returns>A new <see cref="ApiParameterDescription">parameter description</see>.</returns>
        protected virtual ApiParameterDescription NewOrderByParameter(ODataQueryOptionDescriptionContext descriptionContext)
        {
            Arg.NotNull(descriptionContext, nameof(descriptionContext));
            Contract.Ensures(Contract.Result <ApiParameterDescription>() != null);

            var description = Settings.DescriptionProvider.Describe(OrderBy, descriptionContext);

            return(NewParameterDescription(GetName(OrderBy), description, typeof(string)));
        }
Example #7
0
        /// <summary>
        /// Creates and returns a new parameter descriptor for the $count query option.
        /// </summary>
        /// <param name="descriptionContext">The <see cref="ODataQueryOptionDescriptionContext">validation settings</see> used to create the parameter.</param>
        /// <returns>A new <see cref="ApiParameterDescription">parameter description</see>.</returns>
        protected virtual ApiParameterDescription NewCountParameter(ODataQueryOptionDescriptionContext descriptionContext)
        {
            Arg.NotNull(descriptionContext, nameof(descriptionContext));
            Contract.Ensures(Contract.Result <ApiParameterDescription>() != null);

            var description = Settings.DescriptionProvider.Describe(Count, descriptionContext);

            return(NewParameterDescription(GetName(Count), description, typeof(bool), defaultValue: false));
        }
Example #8
0
 internal ODataAttributeVisitor(
     ODataQueryOptionDescriptionContext context,
     IEdmModel?model,
     AllowedQueryOptions allowedQueryOptions,
     Type?resultType,
     bool singleResult)
 {
     this.context        = context;
     AllowedQueryOptions = allowedQueryOptions;
     this.resultType     = resultType;
     IsSingleResult      = singleResult;
     this.model          = model;
     typeResolver        = new StructuredTypeResolver(model);
 }
        /// <summary>
        /// Describes the $skip query option.
        /// </summary>
        /// <param name="context">The current <see cref="ODataQueryOptionDescriptionContext">description context</see>.</param>
        /// <returns>The query option description.</returns>
        protected virtual string DescribeSkip(ODataQueryOptionDescriptionContext context)
        {
            Arg.NotNull(context, nameof(context));
            Contract.Ensures(!string.IsNullOrEmpty(Contract.Result <string>()));

            var description = new StringBuilder();

            description.Append(SR.SkipQueryOptionDesc);

            if (context.MaxSkip != null && context.MaxSkip.Value > 0)
            {
                description.Append(Space);
                description.AppendFormat(CurrentCulture, SR.MaxValueDesc, context.MaxSkip.Value);
            }

            return(description.ToString());
        }
        public void describe_should_return_description_for_select(string[] properties, string expected)
        {
            // arrange
            var provider = new DefaultODataQueryOptionDescriptionProvider();
            var context  = new ODataQueryOptionDescriptionContext();

            for (var i = 0; i < properties.Length; i++)
            {
                context.AllowedSelectProperties.Add(properties[i]);
            }

            // act
            var description = provider.Describe(Select, context);

            // assert
            description.Should().Be(expected);
        }
        /// <inheritdoc />
        public virtual string Describe(AllowedQueryOptions queryOption, ODataQueryOptionDescriptionContext context)
        {
            if ((queryOption < Filter || queryOption > Supported) || (queryOption != Filter && ((int)queryOption % 2 != 0)))
            {
                throw new ArgumentException(SR.MultipleQueryOptionsNotAllowed, nameof(queryOption));
            }

            return(queryOption switch
            {
                Filter => DescribeFilter(context),
                Expand => DescribeExpand(context),
                Select => DescribeSelect(context),
                OrderBy => DescribeOrderBy(context),
                Top => DescribeTop(context),
                Skip => DescribeSkip(context),
                Count => DescribeCount(context),
#pragma warning disable CA1308 // Normalize strings to uppercase
                _ => throw new ArgumentException(SR.UnsupportedQueryOption.FormatDefault(queryOption.ToString().ToLowerInvariant()), nameof(queryOption)),
#pragma warning restore CA1308
            });
        public void describe_should_return_description_for_expand(int maxDepth, string[] properties, string expected)
        {
            // arrange
            var provider = new DefaultODataQueryOptionDescriptionProvider();
            var context  = new ODataQueryOptionDescriptionContext()
            {
                MaxExpansionDepth = maxDepth
            };

            for (var i = 0; i < properties.Length; i++)
            {
                context.AllowedExpandProperties.Add(properties[i]);
            }

            // act
            var description = provider.Describe(Expand, context);

            // assert
            description.Should().Be(expected);
        }
        public void describe_should_return_description_for_orderby(int maxNodeCount, string[] properties, string expected)
        {
            // arrange
            var provider = new DefaultODataQueryOptionDescriptionProvider();
            var context  = new ODataQueryOptionDescriptionContext()
            {
                MaxOrderByNodeCount = maxNodeCount
            };

            for (var i = 0; i < properties.Length; i++)
            {
                context.AllowedOrderByProperties.Add(properties[i]);
            }

            // act
            var description = provider.Describe(OrderBy, context);

            // assert
            description.Should().Be(expected);
        }
Example #14
0
        AllowedQueryOptions GetQueryOptions(DefaultQuerySettings settings, ODataQueryOptionDescriptionContext context)
        {
            Contract.Requires(settings != null);
            Contract.Requires(context != null);

            var queryOptions = ValidationSettings.AllowedQueryOptions;

            if (settings.EnableCount)
            {
                queryOptions |= Count;
            }

            if (settings.EnableExpand)
            {
                queryOptions |= Expand;
            }

            if (settings.EnableFilter)
            {
                queryOptions |= Filter;
            }

            if (settings.EnableOrderBy)
            {
                queryOptions |= OrderBy;
            }

            if (settings.EnableSelect)
            {
                queryOptions |= Select;
            }

            if (settings.MaxTop != null && settings.MaxTop.Value > 0)
            {
                context.MaxTop = settings.MaxTop;
            }

            return(queryOptions);
        }
        /// <inheritdoc />
        public virtual string Describe(AllowedQueryOptions queryOption, ODataQueryOptionDescriptionContext context)
        {
            Arg.NotNull(context, nameof(context));

            if ((queryOption < Filter || queryOption > Supported) || (queryOption != Filter && ((int)queryOption % 2 != 0)))
            {
                throw new ArgumentException(SR.MultipleQueryOptionsNotAllowed, nameof(queryOption));
            }

            switch (queryOption)
            {
            case Filter:
                return(DescribeFilter(context));

            case Expand:
                return(DescribeExpand(context));

            case Select:
                return(DescribeSelect(context));

            case OrderBy:
                return(DescribeOrderBy(context));

            case Top:
                return(DescribeTop(context));

            case Skip:
                return(DescribeSkip(context));

            case Count:
                return(DescribeCount(context));
            }

#pragma warning disable CA1308 // Normalize strings to uppercase
            throw new ArgumentException(SR.UnsupportedQueryOption.FormatDefault(queryOption.ToString().ToLowerInvariant()), nameof(queryOption));
#pragma warning restore CA1308
        }
Example #16
0
        /// <summary>
        /// Creates and returns a new parameter descriptor for the $count query option.
        /// </summary>
        /// <param name="descriptionContext">The <see cref="ODataQueryOptionDescriptionContext">validation settings</see> used to create the parameter.</param>
        /// <returns>A new <see cref="ApiParameterDescription">parameter description</see>.</returns>
        protected virtual ApiParameterDescription NewCountParameter(ODataQueryOptionDescriptionContext descriptionContext)
        {
            var description = Settings.DescriptionProvider.Describe(Count, descriptionContext);

            return(NewParameterDescription(GetName(Count), description, typeof(bool), defaultValue: false));
        }
        /// <inheritdoc />
        public virtual void ApplyTo(ApiDescription apiDescription)
        {
            if (apiDescription == null)
            {
                throw new ArgumentNullException(nameof(apiDescription));
            }

            if (!IsSupported(apiDescription.HttpMethod.Method))
            {
                return;
            }

            var context      = new ODataQueryOptionDescriptionContext(ValidationSettings);
            var model        = apiDescription.EdmModel();
            var queryOptions = GetQueryOptions(apiDescription.ActionDescriptor.Configuration.GetDefaultQuerySettings(), context);
            var singleResult = IsSingleResult(apiDescription, out var resultType);
            var visitor      = new ODataAttributeVisitor(context, model, queryOptions, resultType, singleResult);

            visitor.Visit(apiDescription);

            var options = visitor.AllowedQueryOptions;
            var parameterDescriptions = apiDescription.ParameterDescriptions;

            if (options.HasFlag(Select))
            {
                parameterDescriptions.Add(SetAction(NewSelectParameter(context), apiDescription));
            }

            if (options.HasFlag(Expand))
            {
                parameterDescriptions.Add(SetAction(NewExpandParameter(context), apiDescription));
            }

            if (singleResult)
            {
                return;
            }

            if (options.HasFlag(Filter))
            {
                parameterDescriptions.Add(SetAction(NewFilterParameter(context), apiDescription));
            }

            if (options.HasFlag(OrderBy))
            {
                parameterDescriptions.Add(SetAction(NewOrderByParameter(context), apiDescription));
            }

            if (options.HasFlag(Top))
            {
                parameterDescriptions.Add(SetAction(NewTopParameter(context), apiDescription));
            }

            if (options.HasFlag(Skip))
            {
                parameterDescriptions.Add(SetAction(NewSkipParameter(context), apiDescription));
            }

            if (options.HasFlag(Count))
            {
                parameterDescriptions.Add(SetAction(NewCountParameter(context), apiDescription));
            }
        }
Example #18
0
        /// <summary>
        /// Creates and returns a new parameter descriptor for the $orderby query option.
        /// </summary>
        /// <param name="descriptionContext">The <see cref="ODataQueryOptionDescriptionContext">validation settings</see> used to create the parameter.</param>
        /// <returns>A new <see cref="ApiParameterDescription">parameter description</see>.</returns>
        protected virtual ApiParameterDescription NewOrderByParameter(ODataQueryOptionDescriptionContext descriptionContext)
        {
            var description = Settings.DescriptionProvider.Describe(OrderBy, descriptionContext);

            return(NewParameterDescription(GetName(OrderBy), description, typeof(string)));
        }
Example #19
0
        /// <summary>
        /// Creates and returns a new parameter descriptor for the $top query option.
        /// </summary>
        /// <param name="descriptionContext">The <see cref="ODataQueryOptionDescriptionContext">validation settings</see> used to create the parameter.</param>
        /// <returns>A new <see cref="ApiParameterDescription">parameter description</see>.</returns>
        protected virtual ApiParameterDescription NewTopParameter(ODataQueryOptionDescriptionContext descriptionContext)
        {
            var description = Settings.DescriptionProvider.Describe(Top, descriptionContext);

            return(NewParameterDescription(GetName(Top), description, typeof(int)));
        }