Exemple #1
0
        /// <summary>Attempts to bind a model.</summary>
        /// <param name="bindingContext">The <see cref="T:Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext" />.</param>
        /// <returns>
        /// <para>
        /// A <see cref="T:System.Threading.Tasks.Task" /> which will complete when the model binding process completes.
        /// </para>
        /// <para>
        /// If model binding was successful, the <see cref="P:Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext.Result" /> should have
        /// <see cref="P:Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult.IsModelSet" /> set to <c>true</c>.
        /// </para>
        /// <para>
        /// A model binder that completes successfully should set <see cref="P:Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext.Result" /> to
        /// a value returned from <see cref="M:Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult.Success(System.Object)" />.
        /// </para>
        /// </returns>
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }

            if (bindingContext.ModelType != typeof(FilterParameters))
            {
                return(Task.CompletedTask);
            }


            // Try to fetch the value of the argument by name
            var queryParameters = bindingContext.HttpContext.Request.Query;

            if (!queryParameters.Any())
            {
                var par = new FilterParameters();
                bindingContext.Result = ModelBindingResult.Success(par);
                return(Task.CompletedTask);
            }

            FilterParameters model = ParseModel(queryParameters);

            if (model == null)
            {
                return(Task.CompletedTask);
            }

            bindingContext.Result = ModelBindingResult.Success(model);

            return(Task.CompletedTask);
        }
Exemple #2
0
        private string CreatePagging(FilterParameters filterParameters)
        {
            var pageData = PageDataExtensions.GetPageData(filterParameters.PageSize, filterParameters.CurrentPage);

            if (pageData.skip >= 0)
            {
                return($"OFFSET {pageData.skip} ROWS FETCH NEXT {pageData.take} ROWS ONLY");
            }

            return(string.Empty);
        }
Exemple #3
0
        private string CreateOrderBy(FilterParameters filterParameters)
        {
            var orderColumn = _parameters.DefaultOrderColumn;

            if (!string.IsNullOrWhiteSpace(filterParameters.OrderBy))
            {
                orderColumn = filterParameters.OrderBy;
            }

            if (!typeof(TFilterableEntity).PropertyExists(orderColumn))     //prevent sql injection
            {
                throw new Exception($"The property {orderColumn} should exists in {typeof(TFilterableEntity).Name}");
            }

            return($" ORDER BY {orderColumn} {filterParameters.OrderKind} ");
        }
Exemple #4
0
        private FilterParameters ParseModel(IQueryCollection queryParameters)
        {
            var columnNames = queryParameters[FilterColumnName];
            var groups      = columnNames.GroupBy(s => s).Select(
                s => new { Name = s.Key, Count = s.Count() });

            var columns = groups.ToDictionary(arg => arg.Name, arg1 => arg1.Count);

            var filter = new FilterParameters();

            foreach (var name in columns.Keys)
            {
                var expectedCount  = columns[name];
                var valueParameter = string.Format(FilterColumnValue, name);
                var values         = new string[expectedCount];

                if (queryParameters.ContainsKey(valueParameter))
                {
                    var parameterValues = queryParameters[valueParameter];
                    values = parameterValues;
                }

                var operatorParameter   = string.Format(FilterParameterOperator, name);
                var comparisonOperators = ParseEnum(queryParameters, operatorParameter, expectedCount, FilterComparisonOperators.None);
                var logicalParameter    = string.Format(FilterParameterNext, name);
                var logicalOperators    = ParseEnum(queryParameters, logicalParameter, expectedCount, FilterLogicalOperators.None);

                for (int i = 0; i < expectedCount; i++)
                {
                    if (!string.IsNullOrWhiteSpace(values[i]) && comparisonOperators[i] != FilterComparisonOperators.None)
                    {
                        var filterStatement = new FilterStatement();
                        filterStatement.ParameterName      = name;
                        filterStatement.ParameterValue     = values[i];
                        filterStatement.ComparisonOperator = comparisonOperators[i];
                        filterStatement.LogicalOperator    = logicalOperators[i];
                        filter.Statements.Add(filterStatement);
                    }
                }
            }

            if (queryParameters.ContainsKey(PageSize))
            {
                if (int.TryParse(queryParameters[PageSize], NumberStyles.None, CultureInfo.InvariantCulture,
                                 out var res))
                {
                    filter.PageSize = res;
                }
            }

            filter.PageSize    = ParseInt(queryParameters, PageSize, -1);
            filter.CurrentPage = ParseInt(queryParameters, CurrentPage, -1);

            if (queryParameters.ContainsKey(OrderBy))
            {
                filter.OrderKind = ParseEnum(queryParameters, OrderKind, 1, Filterable.OrderKind.Asc).First();
                filter.OrderBy   = queryParameters[OrderBy];
            }

            return(filter);
        }
Exemple #5
0
 private (string sql, object[] parameters) CreateWhere(FilterParameters filterParameters)
 {
     return(_filterStatementParser.Parse(filterParameters.Statements, _parameters));
 }
Exemple #6
0
        public async Task <PagedResult <TFilterableEntity> > FilterAsync(DbContext context, IResourceMandatoryPredicateFactory <TEntity, TKey> mandatoryPredicateFactory, FilterParameters filterParameters)
        {
            var orderByClause   = CreateOrderBy(filterParameters);
            var paggingClause   = CreatePagging(filterParameters);
            var whereParameters = CreateWhere(filterParameters);

            var sqlCount = _parameters.Sql
                           .Replace(OrderByClause, string.Empty, StringComparison.OrdinalIgnoreCase)
                           .Replace(PaggingClause, string.Empty, StringComparison.OrdinalIgnoreCase)
                           .Replace(WhereClause, whereParameters.sql, StringComparison.OrdinalIgnoreCase);

            var sqlResult = _parameters.Sql
                            .Replace(OrderByClause, orderByClause, StringComparison.OrdinalIgnoreCase)
                            .Replace(PaggingClause, paggingClause, StringComparison.OrdinalIgnoreCase)
                            .Replace(WhereClause, whereParameters.sql, StringComparison.OrdinalIgnoreCase);

            var count = await context.Set <TFilterableEntity>().FromSqlRaw(sqlCount, whereParameters.parameters).LongCountAsync();

            var result = await context.Set <TFilterableEntity>().FromSqlRaw(sqlResult, whereParameters.parameters).ToArrayAsync();

            return(new PagedResult <TFilterableEntity>(count, result));
        }
        public async Task <PagedResult <TFilterableEntity> > FilterAsync(DbContext context, IResourceMandatoryPredicateFactory <TEntity, TKey> mandatoryPredicateFactory, FilterParameters filterParameters)
        {
            var mandatoryPredicate = mandatoryPredicateFactory.GetMandatoryPredicates();

            var predicate = LinqKit.PredicateBuilder.New <TEntity>(true);

            foreach (var filter in filterParameters.Statements)
            {
                ISpecification <TEntity> specification = Create(filter);

                if (specification == null)
                {
                    continue;
                }

                if (filter.LogicalOperator == FilterLogicalOperators.Or)
                {
                    predicate.Or(specification.IsSatisfiedBy());
                }
                else
                {
                    predicate.And(specification.IsSatisfiedBy());
                }
            }

            var count = await context.Set <TEntity>().AsExpandable().Where(mandatoryPredicate).Where(predicate).LongCountAsync();

            var entityQuery = context.Set <TEntity>().AsQueryable();

            if (_parameters.IncludeProperties != null)
            {
                foreach (var includedProperty in _parameters.IncludeProperties)
                {
                    entityQuery = entityQuery.Include(includedProperty);
                }
            }

            var query = entityQuery.AsExpandable().Where(mandatoryPredicate).Where(predicate);

            if (!string.IsNullOrWhiteSpace(filterParameters.OrderBy))
            {
                var sortOrder = filterParameters.OrderKind == OrderKind.Asc? ListSortDirection.Ascending: ListSortDirection.Descending;

                var orderByColumn = filterParameters.OrderBy.ToLower();

                if (_parameters.SortFieldsMaping.ContainsKey(orderByColumn))
                {
                    orderByColumn = _parameters.SortFieldsMaping[orderByColumn];
                }

                query = query.OrderBy(orderByColumn, sortOrder);
            }

            var pageData = PageDataExtensions.GetPageData(filterParameters.PageSize, filterParameters.CurrentPage);

            if (pageData.skip >= 0)
            {
                query = query.Skip(pageData.skip).Take(pageData.take);
            }

            TFilterableEntity[] entities;

            if (_parameters.DirectProject)
            {
                entities = await _mapper.ProjectTo <TFilterableEntity>(query).ToArrayAsync();
            }
            else
            {
                var queryEntities = await query.ToArrayAsync();

                entities = _mapper.Map <TFilterableEntity[]>(queryEntities);
            }

            return(new PagedResult <TFilterableEntity>(count, entities));
        }