public override void OnActionExecuting(ActionExecutingContext context) { ParameterDescriptor dynamicQueryParameter = context.ActionDescriptor .Parameters .FirstOrDefault(x => x.ParameterType == typeof(DynamicQueryOptions)); DynamicQueryBuilderSettings dqbSettings = context .HttpContext .RequestServices? .GetService(typeof(DynamicQueryBuilderSettings)) as DynamicQueryBuilderSettings ?? new DynamicQueryBuilderSettings(); if (dynamicQueryParameter == null) { base.OnActionExecuting(context); return; } string queryValue = context.HttpContext.Request.QueryString.Value; if (dqbSettings.QueryOptionsResolver != null) { if (dqbSettings.QueryOptionsResolver is QueryStringResolver qsResolver) { string[] values; if (!string.IsNullOrEmpty(qsResolver.ResolveFrom)) { NameValueCollection resolveParameterValues = HttpUtility.ParseQueryString(queryValue); values = resolveParameterValues.GetValues(qsResolver.ResolveFrom) ?? new string[] { string.Empty }; } else { values = new string[] { queryValue }; } queryValue = values[0]; if (qsResolver.DecodeFunction != null) { queryValue = qsResolver.DecodeFunction(queryValue); } else if (QueryStringParser.IsQueryStringEncoded(queryValue)) { queryValue = HttpUtility.UrlDecode(queryValue); } } else if (dqbSettings.QueryOptionsResolver is HttpHeaderResolver hhResolver) { string rawHeaderValue = context .HttpContext .Request .Headers[hhResolver.HttpHeaderName] .FirstOrDefault() ?? string.Empty; queryValue = hhResolver.DecodeFunction != null ? hhResolver.DecodeFunction(rawHeaderValue) : rawHeaderValue; } } DynamicQueryOptions parsedOptions = ExpressionBuilder.ParseQueryOptions( queryValue, dqbSettings.CustomOpCodes); parsedOptions.UsesCaseInsensitiveSource = dqbSettings.UsesCaseInsensitiveSource; parsedOptions.IgnorePredefinedOrders = dqbSettings.IgnorePredefinedOrders; if (parsedOptions.PaginationOption != null) { parsedOptions.PaginationOption.AssignDataSetCount = _includeDataSetCountToPagination; if (parsedOptions.PaginationOption.Count > _maxCountSize) { if (_exceededPaginationCountBehaviour == PaginationBehaviour.GetMax) { parsedOptions.PaginationOption.Count = _maxCountSize; } else { throw new MaximumResultSetExceededException( $"Given count {parsedOptions.PaginationOption.Count} exceeds the maximum amount"); } } else if (parsedOptions.PaginationOption.Count <= 0) { parsedOptions.PaginationOption.Count = 1; } if (parsedOptions.PaginationOption.Offset < 0) { parsedOptions.PaginationOption.Offset = 0; } } else if (_includeDataSetCountToPagination && parsedOptions.PaginationOption == null) { parsedOptions.PaginationOption = new PaginationOption { AssignDataSetCount = true }; } context.ActionArguments[dynamicQueryParameter.Name] = parsedOptions; base.OnActionExecuting(context); }
/// <summary> /// Parses a Querystring into DynamicQueryOptions instance. /// </summary> /// <param name="query">QueryString to parse.</param> /// <param name="opShortCodes">Custom operation shortcodes.</param> /// <returns>Parsed DynamicQueryOptions instance.</returns> public static DynamicQueryOptions ParseQueryOptions(string query, CustomOpCodes opShortCodes = null) { try { var dynamicQueryOptions = new DynamicQueryOptions(); if (string.IsNullOrEmpty(query)) { return(dynamicQueryOptions); } ////+ character issue ////https://docs.microsoft.com/en-us/dotnet/api/system.web.httputility.urlencode?redirectedfrom=MSDN&view=net-5.0#System_Web_HttpUtility_UrlEncode_System_String_ if (QueryStringParser.IsQueryStringEncoded(query)) { query = HttpUtility.UrlDecode(query); } DynamicQueryOptions innerQueryOptions = null; const string innerMemberKey = "v=("; int indexOfInnerMemberKey = query.IndexOf(innerMemberKey, StringComparison.Ordinal); if (indexOfInnerMemberKey != -1) { indexOfInnerMemberKey += innerMemberKey.Length; string innerQuery = query.Substring(indexOfInnerMemberKey, query.LastIndexOf(')') - indexOfInnerMemberKey); innerQueryOptions = ParseQueryOptions(innerQuery, opShortCodes); query = query.Replace(innerQuery, string.Empty); } string[] defaultArrayValue = new string[0]; NameValueCollection queryCollection = HttpUtility.ParseQueryString(query); IEnumerable <QueryStringParserResult> queryStringParserResults = QueryStringParser .GetAllParameterWithValue(query) .Where(e => !string.IsNullOrEmpty(e.Value) && e.Value.Contains(InternalConstants.PLUS_CHARACTER)).ToList(); if (queryStringParserResults.Any()) { QueryStringParser.ReplaceNameValueCollection(queryStringParserResults, queryCollection, InternalConstants.PARAMETER_VALUE_KEY); } string[] operations = queryCollection .GetValues(InternalConstants.OPERATION_PARAMETER_KEY) ?.Select(x => x.ClearSpaces()) .ToArray() ?? defaultArrayValue; string[] parameterNames = queryCollection .GetValues(InternalConstants.PARAMETER_NAME_KEY) ?.Select(x => x.ClearSpaces()) .ToArray() ?? defaultArrayValue; string[] parameterValues = queryCollection .GetValues(InternalConstants.PARAMETER_VALUE_KEY) ?.ToArray() ?? defaultArrayValue; string[] sortOptions = queryCollection .GetValues(InternalConstants.SORT_OPTIONS_PARAMETER_KEY) ?.Select(x => x.ClearSpaces()) .ToArray() ?? defaultArrayValue; string[] offsetOptions = queryCollection .GetValues(InternalConstants.OFFSET_PARAMETER_KEY) ?.Select(x => x.ClearSpaces()) .ToArray() ?? defaultArrayValue; string[] countOptions = queryCollection .GetValues(InternalConstants.COUNT_PARAMETER_KEY) ?.Select(x => x.ClearSpaces()) .ToArray() ?? defaultArrayValue; PopulateDynamicQueryOptions( dynamicQueryOptions, operations, parameterNames, parameterValues, sortOptions, offsetOptions, countOptions, opShortCodes: opShortCodes ?? Defaults.DefaultOpShortCodes, memberQueryOptions: innerQueryOptions); return(dynamicQueryOptions); } catch (Exception ex) { throw new DynamicQueryException("DynamicQueryBuilder has encountered an unhandled exception", query, ex); } }