/// <summary> /// Get the page size. /// </summary> /// <param name="actionExecutedContext">The response value.</param> /// <param name="responseValue">The response value.</param> /// <param name="singleResultCollection">The content as SingleResult.Queryable.</param> /// <param name="actionDescriptor">The action context, i.e. action and controller name.</param> /// <param name="request">The request.</param> private void GetModelBoundPageSize( ActionExecutedContext actionExecutedContext, object responseValue, IQueryable singleResultCollection, ControllerActionDescriptor actionDescriptor, HttpRequest request) { ODataQueryContext queryContext; try { queryContext = GetODataQueryContext(responseValue, singleResultCollection, actionDescriptor, request); } catch (InvalidOperationException e) { actionExecutedContext.Result = CreateBadRequestResult(Error.Format(SRResources.UriQueryStringInvalid, e.Message), e); return; } ModelBoundQuerySettings querySettings = EdmHelpers.GetModelBoundQuerySettings(queryContext.TargetProperty, queryContext.TargetStructuredType, queryContext.Model); if (querySettings != null && querySettings.PageSize.HasValue) { _querySettings.ModelBoundPageSize = querySettings.PageSize; } }
/// <summary> /// Copy the $select configuration of properties. /// </summary> internal static void CopySelectConfigurations(this ModelBoundQuerySettings settings, Dictionary <string, SelectExpandType> selectConfigurations) { settings.SelectConfigurations.Clear(); foreach (var selectConfiguration in selectConfigurations) { settings.SelectConfigurations.Add(selectConfiguration.Key, selectConfiguration.Value); } }
/// <summary> /// Copy the $filter configuration of properties. /// </summary> internal static void CopyFilterConfigurations(this ModelBoundQuerySettings settings, Dictionary <string, bool> filterConfigurations) { settings.FilterConfigurations.Clear(); foreach (var filterConfiguration in filterConfigurations) { settings.FilterConfigurations.Add(filterConfiguration.Key, filterConfiguration.Value); } }
/// <summary> /// Copy the $orderby configuration of properties. /// </summary> internal static void CopyOrderByConfigurations(this ModelBoundQuerySettings settings, Dictionary <string, bool> orderByConfigurations) { settings.OrderByConfigurations.Clear(); foreach (var orderByConfiguration in orderByConfigurations) { settings.OrderByConfigurations.Add(orderByConfiguration.Key, orderByConfiguration.Value); } }
/// <summary> /// Copy the <see cref="ExpandConfiguration"/>s of navigation properties. /// </summary> internal static void CopyExpandConfigurations(this ModelBoundQuerySettings settings, Dictionary <string, ExpandConfiguration> expandConfigurations) { settings.ExpandConfigurations.Clear(); foreach (var expandConfiguration in expandConfigurations) { settings.ExpandConfigurations.Add(expandConfiguration.Key, expandConfiguration.Value); } }
// Process $levels in SelectedItems. private IEnumerable <SelectItem> ProcessLevels( IEnumerable <SelectItem> selectItems, int levelsMaxLiteralExpansionDepth, ModelBoundQuerySettings querySettings, out bool levelsEncountered, out bool isMaxLevel) { levelsEncountered = false; isMaxLevel = false; IList <SelectItem> items = new List <SelectItem>(); foreach (SelectItem selectItem in selectItems) { ExpandedNavigationSelectItem item = selectItem as ExpandedNavigationSelectItem; if (item == null) { // There is no $levels in non-ExpandedNavigationSelectItem. items.Add(selectItem); } else { bool levelsEncouteredInExpand; bool isMaxLevelInExpand; // Process $levels in ExpandedNavigationSelectItem. ExpandedNavigationSelectItem expandItem = ProcessLevels( item, levelsMaxLiteralExpansionDepth, querySettings, out levelsEncouteredInExpand, out isMaxLevelInExpand); if (item.LevelsOption != null && item.LevelsOption.Level > 0 && expandItem == null) { // Abandon this attempt if any of the items failed to expand return(null); } else if (item.LevelsOption != null) { // The expansion would be volatile if any of the expand item is max level isMaxLevel = isMaxLevel || isMaxLevelInExpand; } levelsEncountered = levelsEncountered || levelsEncouteredInExpand; if (expandItem != null) { items.Add(expandItem); } } } return(items); }
internal SelectExpandClause ProcessLevels() { bool levelsEncountered; bool isMaxLevel; ModelBoundQuerySettings querySettings = Context.Model.GetModelBoundQuerySettings(Context.TargetProperty, Context.TargetStructuredType, Context.DefaultQuerySettings); return(ProcessLevels(SelectExpandClause, LevelsMaxLiteralExpansionDepth < 0 ? ODataValidationSettings.DefaultMaxExpansionDepth : LevelsMaxLiteralExpansionDepth, querySettings, out levelsEncountered, out isMaxLevel)); }
internal static bool Expandable(this ModelBoundQuerySettings settings, string propertyName) { ExpandConfiguration expandConfiguration; if (settings.ExpandConfigurations.TryGetValue(propertyName, out expandConfiguration)) { return(expandConfiguration.ExpandType != SelectExpandType.Disabled); } else { return(settings.DefaultExpandType.HasValue && settings.DefaultExpandType != SelectExpandType.Disabled); } }
internal static bool IsAutomaticSelect(this ModelBoundQuerySettings settings, string propertyName) { SelectExpandType selectExpandType; if (settings.SelectConfigurations.TryGetValue(propertyName, out selectExpandType)) { return(selectExpandType == SelectExpandType.Automatic); } else { return(settings.DefaultSelectType.HasValue && settings.DefaultSelectType == SelectExpandType.Automatic); } }
internal static bool Filterable(this ModelBoundQuerySettings settings, string propertyName) { bool enable; if (settings.FilterConfigurations.TryGetValue(propertyName, out enable)) { return(enable); } else { return(settings.DefaultEnableFilter == true); } }
/// <summary> /// Copy and create new instance of the <see cref="ModelBoundQuerySettings"/> class /// </summary> public ModelBoundQuerySettings(ModelBoundQuerySettings querySettings) { if (querySettings == null) { throw new ArgumentNullException(nameof(querySettings)); } _maxTop = querySettings.MaxTop; PageSize = querySettings.PageSize; Countable = querySettings.Countable; DefaultEnableFilter = querySettings.DefaultEnableFilter; DefaultEnableOrderBy = querySettings.DefaultEnableOrderBy; DefaultExpandType = querySettings.DefaultExpandType; DefaultMaxDepth = querySettings.DefaultMaxDepth; DefaultSelectType = querySettings.DefaultSelectType; CopyOrderByConfigurations(querySettings.OrderByConfigurations); CopyFilterConfigurations(querySettings.FilterConfigurations); CopyExpandConfigurations(querySettings.ExpandConfigurations); CopySelectConfigurations(querySettings.SelectConfigurations); }
private static int GetMaxExpandDepth(ModelBoundQuerySettings querySettings, string propertyName) { int result = 0; if (querySettings != null) { ExpandConfiguration expandConfiguration; if (querySettings.ExpandConfigurations.TryGetValue(propertyName, out expandConfiguration)) { result = expandConfiguration.MaxDepth; } else { if (querySettings.DefaultExpandType.HasValue && querySettings.DefaultExpandType != SelectExpandType.Disabled) { result = querySettings.DefaultMaxDepth; } } } return(result); }
// Process $levels in SelectExpandClause. private SelectExpandClause ProcessLevels( SelectExpandClause selectExpandClause, int levelsMaxLiteralExpansionDepth, ModelBoundQuerySettings querySettings, out bool levelsEncountered, out bool isMaxLevel) { levelsEncountered = false; isMaxLevel = false; if (selectExpandClause == null) { return(null); } // Process $levels in SelectItems of SelectExpandClause. IEnumerable <SelectItem> selectItems = ProcessLevels( selectExpandClause.SelectedItems, levelsMaxLiteralExpansionDepth, querySettings, out levelsEncountered, out isMaxLevel); if (selectItems == null) { return(null); } else if (levelsEncountered) { return(new SelectExpandClause(selectItems, selectExpandClause.AllSelected)); } else { // Return the original SelectExpandClause if no $levels is found. return(selectExpandClause); } }
// Process $levels in ExpandedNavigationSelectItem. private ExpandedNavigationSelectItem ProcessLevels( ExpandedNavigationSelectItem expandItem, int levelsMaxLiteralExpansionDepth, ModelBoundQuerySettings querySettings, out bool levelsEncounteredInExpand, out bool isMaxLevelInExpand) { int level; isMaxLevelInExpand = false; if (expandItem.LevelsOption == null) { levelsEncounteredInExpand = false; level = 1; } else { levelsEncounteredInExpand = true; if (expandItem.LevelsOption.IsMaxLevel) { isMaxLevelInExpand = true; level = levelsMaxLiteralExpansionDepth; } else { level = (int)expandItem.LevelsOption.Level; } } // Do not expand when: // 1. $levels is equal to or less than 0. // 2. $levels value is greater than current MaxExpansionDepth if (level <= 0 || level > levelsMaxLiteralExpansionDepth) { return(null); } ExpandedNavigationSelectItem item = null; SelectExpandClause currentSelectExpandClause = null; SelectExpandClause selectExpandClause = null; bool levelsEncounteredInInnerExpand = false; bool isMaxLevelInInnerExpand = false; var entityType = expandItem.NavigationSource.EntityType(); IEdmNavigationProperty navigationProperty = (expandItem.PathToNavigationProperty.LastSegment as NavigationPropertySegment).NavigationProperty; ModelBoundQuerySettings nestQuerySettings = Context.Model.GetModelBoundQuerySettings(navigationProperty, navigationProperty.ToEntityType()); // Try different expansion depth until expandItem.SelectAndExpand is successfully expanded while (selectExpandClause == null && level > 0) { selectExpandClause = ProcessLevels( expandItem.SelectAndExpand, levelsMaxLiteralExpansionDepth - level, nestQuerySettings, out levelsEncounteredInInnerExpand, out isMaxLevelInInnerExpand); level--; } if (selectExpandClause == null) { return(null); } // Correct level value level++; List <SelectItem> originAutoSelectItems; List <SelectItem> originAutoExpandItems; int maxDepth = GetMaxExpandDepth(querySettings, navigationProperty.Name); if (maxDepth == 0 || levelsMaxLiteralExpansionDepth > maxDepth) { maxDepth = levelsMaxLiteralExpansionDepth; } GetAutoSelectExpandItems( entityType, Context.Model, expandItem.NavigationSource, selectExpandClause.AllSelected, nestQuerySettings, maxDepth - 1, out originAutoSelectItems, out originAutoExpandItems); if (expandItem.SelectAndExpand.SelectedItems.Any(it => it is PathSelectItem)) { originAutoSelectItems.Clear(); } if (level > 1) { RemoveSameExpandItem(navigationProperty, originAutoExpandItems); } List <SelectItem> autoExpandItems = new List <SelectItem>(originAutoExpandItems); bool hasAutoSelectExpandInExpand = (originAutoSelectItems.Count + originAutoExpandItems.Count != 0); bool allSelected = originAutoSelectItems.Count == 0 && selectExpandClause.AllSelected; while (level > 0) { autoExpandItems = RemoveExpandItemExceedMaxDepth(maxDepth - level, originAutoExpandItems); if (item == null) { if (hasAutoSelectExpandInExpand) { currentSelectExpandClause = new SelectExpandClause( Array.Empty <SelectItem>().Concat(selectExpandClause.SelectedItems) .Concat(originAutoSelectItems).Concat(autoExpandItems), allSelected); } else { currentSelectExpandClause = selectExpandClause; } } else if (selectExpandClause.AllSelected) { // Concat the processed items currentSelectExpandClause = new SelectExpandClause( new SelectItem[] { item }.Concat(selectExpandClause.SelectedItems) .Concat(originAutoSelectItems).Concat(autoExpandItems), allSelected); } else { // PathSelectItem is needed for the expanded item if AllSelected is false. PathSelectItem pathSelectItem = new PathSelectItem( new ODataSelectPath(expandItem.PathToNavigationProperty)); // Keep default SelectItems before expanded item to keep consistent with normal SelectExpandClause SelectItem[] items = new SelectItem[] { item, pathSelectItem }; currentSelectExpandClause = new SelectExpandClause( Array.Empty <SelectItem>().Concat(selectExpandClause.SelectedItems) .Concat(items) .Concat(originAutoSelectItems).Concat(autoExpandItems), allSelected); } // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause. item = new ExpandedNavigationSelectItem( expandItem.PathToNavigationProperty, expandItem.NavigationSource, currentSelectExpandClause, expandItem.FilterOption, expandItem.OrderByOption, expandItem.TopOption, expandItem.SkipOption, expandItem.CountOption, expandItem.SearchOption, null, expandItem.ComputeOption, expandItem.ApplyOption); level--; // Need expand and construct selectExpandClause every time if it is max level in inner expand if (isMaxLevelInInnerExpand) { selectExpandClause = ProcessLevels( expandItem.SelectAndExpand, levelsMaxLiteralExpansionDepth - level, nestQuerySettings, out levelsEncounteredInInnerExpand, out isMaxLevelInInnerExpand); } } levelsEncounteredInExpand = levelsEncounteredInExpand || levelsEncounteredInInnerExpand || hasAutoSelectExpandInExpand; isMaxLevelInExpand = isMaxLevelInExpand || isMaxLevelInInnerExpand; return(item); }
private void GetAutoSelectExpandItems(IEdmEntityType baseEntityType, IEdmModel model, IEdmNavigationSource navigationSource, bool isAllSelected, ModelBoundQuerySettings modelBoundQuerySettings, int depth, out List <SelectItem> autoSelectItems, out List <SelectItem> autoExpandItems) { autoSelectItems = new List <SelectItem>(); autoExpandItems = new List <SelectItem>(); if (baseEntityType == null) { return; } IList <SelectModelPath> autoSelectProperties = model.GetAutoSelectPaths(baseEntityType, null, modelBoundQuerySettings); foreach (var autoSelectProperty in autoSelectProperties) { ODataSelectPath odataSelectPath = BuildSelectPath(autoSelectProperty, navigationSource); PathSelectItem pathSelectItem = new PathSelectItem(odataSelectPath); autoSelectItems.Add(pathSelectItem); } depth--; if (depth < 0) { return; } IList <ExpandModelPath> autoExpandNavigationProperties = model.GetAutoExpandPaths(baseEntityType, null, !isAllSelected, modelBoundQuerySettings); foreach (ExpandModelPath itemPath in autoExpandNavigationProperties) { string navigationPath = itemPath.NavigationPropertyPath; IEdmNavigationProperty navigationProperty = itemPath.Navigation; IEdmNavigationSource currentEdmNavigationSource; if (navigationPath != null) { currentEdmNavigationSource = navigationSource.FindNavigationTarget(navigationProperty); } else { currentEdmNavigationSource = navigationSource.FindNavigationTarget(navigationProperty, new EdmPathExpression(navigationPath)); } if (currentEdmNavigationSource != null) { ODataExpandPath expandPath = BuildExpandPath(itemPath, navigationSource, currentEdmNavigationSource); SelectExpandClause selectExpandClause = new SelectExpandClause(new List <SelectItem>(), true); ExpandedNavigationSelectItem item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource, selectExpandClause); modelBoundQuerySettings = model.GetModelBoundQuerySettings(navigationProperty, navigationProperty.ToEntityType()); List <SelectItem> nestedSelectItems; List <SelectItem> nestedExpandItems; int maxExpandDepth = GetMaxExpandDepth(modelBoundQuerySettings, navigationProperty.Name); if (maxExpandDepth != 0 && maxExpandDepth < depth) { depth = maxExpandDepth; } GetAutoSelectExpandItems( currentEdmNavigationSource.EntityType(), model, item.NavigationSource, true, modelBoundQuerySettings, depth, out nestedSelectItems, out nestedExpandItems); selectExpandClause = new SelectExpandClause(nestedSelectItems.Concat(nestedExpandItems), nestedSelectItems.Count == 0); item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource, selectExpandClause); autoExpandItems.Add(item); if (!isAllSelected || autoSelectProperties.Any()) { PathSelectItem pathSelectItem = new PathSelectItem(new ODataSelectPath(expandPath)); autoExpandItems.Add(pathSelectItem); } } } }
private void GetAutoSelectExpandItems( IEdmEntityType baseEntityType, IEdmModel model, IEdmNavigationSource navigationSource, bool isAllSelected, ModelBoundQuerySettings modelBoundQuerySettings, int depth, out List <SelectItem> autoSelectItems, out List <SelectItem> autoExpandItems) { autoSelectItems = new List <SelectItem>(); autoExpandItems = new List <SelectItem>(); var autoSelectProperties = EdmHelpers.GetAutoSelectProperties(null, baseEntityType, model, modelBoundQuerySettings); foreach (var autoSelectProperty in autoSelectProperties) { List <ODataPathSegment> pathSegments = new List <ODataPathSegment>() { new PropertySegment(autoSelectProperty) }; PathSelectItem pathSelectItem = new PathSelectItem( new ODataSelectPath(pathSegments)); autoSelectItems.Add(pathSelectItem); } depth--; if (depth < 0) { return; } var autoExpandNavigationProperties = EdmHelpers.GetAutoExpandNavigationProperties(null, baseEntityType, model, !isAllSelected, modelBoundQuerySettings); foreach (var navigationProperty in autoExpandNavigationProperties) { IEdmNavigationSource currentEdmNavigationSource = navigationSource.FindNavigationTarget(navigationProperty); if (currentEdmNavigationSource != null) { List <ODataPathSegment> pathSegments = new List <ODataPathSegment>() { new NavigationPropertySegment(navigationProperty, currentEdmNavigationSource) }; ODataExpandPath expandPath = new ODataExpandPath(pathSegments); SelectExpandClause selectExpandClause = new SelectExpandClause(new List <SelectItem>(), true); ExpandedNavigationSelectItem item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource, selectExpandClause); modelBoundQuerySettings = EdmHelpers.GetModelBoundQuerySettings(navigationProperty, navigationProperty.ToEntityType(), model); List <SelectItem> nestedSelectItems; List <SelectItem> nestedExpandItems; int maxExpandDepth = GetMaxExpandDepth(modelBoundQuerySettings, navigationProperty.Name); if (maxExpandDepth != 0 && maxExpandDepth < depth) { depth = maxExpandDepth; } GetAutoSelectExpandItems( currentEdmNavigationSource.EntityType(), model, item.NavigationSource, true, modelBoundQuerySettings, depth, out nestedSelectItems, out nestedExpandItems); selectExpandClause = new SelectExpandClause(nestedSelectItems.Concat(nestedExpandItems), nestedSelectItems.Count == 0); item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource, selectExpandClause); autoExpandItems.Add(item); if (!isAllSelected || autoSelectProperties.Any()) { PathSelectItem pathSelectItem = new PathSelectItem( new ODataSelectPath(pathSegments)); autoExpandItems.Add(pathSelectItem); } } } }