/// <summary> /// Call the next page request when there is another page of data. /// </summary> /// <param name="token"></param> /// <returns>The task object that represents the results of this asynchronous operation.</returns> /// <exception cref="Microsoft.Graph.ServiceException">Thrown when the service encounters an error with /// a request.</exception> private async Task InterpageIterateAsync(CancellationToken token) { State = PagingState.InterpageIteration; // Get the next page if it is available and queue the items for processing. if (_currentPage.AdditionalData.TryGetValue(Constants.OdataInstanceAnnotations.NextLink, out object nextlink)) { // We need access to the NextPageRequest to call and get the next page. ICollectionPage<TEntity> doesn't define NextPageRequest. // We are making this dynamic so we can access NextPageRequest. dynamic page = _currentPage; // Call the MSGraph API to get the next page of results and set that page as the currentPage. _currentPage = await page.NextPageRequest.GetAsync(token).ConfigureAwait(false); // Add all of the items returned in the response to the queue. if (_currentPage.Count > 0) { foreach (TEntity entity in _currentPage) { _pageItemQueue.Enqueue(entity); } } } // Detect nextLink loop if (_currentPage.AdditionalData.TryGetValue(Constants.OdataInstanceAnnotations.NextLink, out object nextNextLink) && nextlink.Equals(nextNextLink)) { throw new ServiceException(new Error() { Message = $"Detected nextLink loop. Nextlink value: {Nextlink}" }); } }
// Uses a page iterator to get all directoryObjects // in a collection and cast them to a specific type // Will exclude any objects that cannot be case to the // requested type protected async Task <List <T> > GetAllPagesAsType <T>( GraphServiceClient graphClient, ICollectionPage <DirectoryObject> page) where T : class { var allItems = new List <T>(); var pageIterator = PageIterator <DirectoryObject> .CreatePageIterator( graphClient, page, (item) => { // This code executes for each item in the // collection if (item is T) { // Only add if the item is the requested type allItems.Add(item as T); } return(true); } ); await pageIterator.IterateAsync(); return(allItems); }
/// <summary> /// /// </summary> /// <param name="graphClient">Authenticated GraphServiceClient object.</param> /// <param name="page">Result page object from .GetAsync() method</param> /// <typeparam name="TSource">Source collection member type (e.g. DirectoryObject, User, Group)</typeparam> /// <typeparam name="TResult">Result collection member type (e.g. Group, User)</typeparam> /// <returns></returns> protected async Task <IEnumerable <TResult>?> AllPagesAsync <TSource, TResult>( IBaseClient graphClient, ICollectionPage <TSource> page) where TResult : class { if (page == null) { return(null); } var allItems = new List <TResult>(); var pageIterator = PageIterator <TSource> .CreatePageIterator( graphClient, page, (item) => { // This code executes for each item in the // collection if (item is TResult t) { // Only add if the item is the requested type allItems.Add(t); } return(true); } ); await pageIterator.IterateAsync(); return(allItems); }
public CollectionPageController ( ILrpNavigation navigation, ICollectionPageViewModel <TItem> collectionPageViewModel, ICollectionPage <TItem> collectionPage, IItemMvcBuilder <TItem> itemMvcBuilder ) { _navigation = navigation ?? throw new ArgumentNullException(nameof(navigation)); _collectionPageViewModel = collectionPageViewModel ?? throw new ArgumentNullException(nameof(collectionPageViewModel)); _collectionPage = collectionPage ?? throw new ArgumentNullException(nameof(collectionPage)); _itemMvcBuilder = itemMvcBuilder ?? throw new ArgumentNullException(nameof(itemMvcBuilder)); WirePage(); }
/// <summary> /// Iterate across the content of a a single results page with the callback. /// </summary> /// <returns>A boolean value that indicates whether the callback cancelled /// iterating across the page results or whether there are more pages to page. /// A return value of false indicates that the iterator should stop iterating.</returns> private bool IntrapageIterate() { State = PagingState.IntrapageIteration; while (_pageItemQueue.Count != 0) // && shouldContinue) { bool shouldContinue = _processPageItemCallback(_pageItemQueue.Dequeue()); // Cancel processing of items in the page and stop requesting more pages. if (!shouldContinue) { State = PagingState.Paused; return(shouldContinue); } } // There are more pages ready to be paged. if (_currentPage.AdditionalData.TryGetValue(Constants.OdataInstanceAnnotations.NextLink, out object nextlink)) { Nextlink = nextlink as string; return(true); } // There are no pages CURRENTLY ready to be paged. Attempt to call delta query later. else if (_currentPage.AdditionalData.TryGetValue(Constants.OdataInstanceAnnotations.DeltaLink, out object deltalink)) { Deltalink = deltalink as string; State = PagingState.Delta; Nextlink = string.Empty; // Setup deltalink request. Using dynamic to access the NextPageRequest. dynamic page = _currentPage; page.InitializeNextPageRequest(this._client, Deltalink); _currentPage = page; return(false); } // Paging has completed - no more nextlinks. else { State = PagingState.Complete; Nextlink = string.Empty; return(false); } }
private static async Task <bool> AnyAsync <TItem>(ICollectionPage <TItem> collectionPage, Func <TItem, bool> predicate) { dynamic page = collectionPage; while (true) { if (Enumerable.Any(page.CurrentPage, predicate)) { return(true); } if (page.NextPageRequest == null) { return(false); } page = await page.NextPageRequest.GetAsync(); } }
private static async Task <TItem[]> GetAllAsync <TItem>(ICollectionPage <TItem> collectionPage) { var list = new List <TItem>(); dynamic page = collectionPage; while (true) { list.AddRange(page.CurrentPage); if (page.NextPageRequest == null) { break; } page = await page.NextPageRequest.GetAsync(); } return(list.ToArray()); }
// Uses a page iterator to get all objects in a collection protected async Task <List <T> > GetAllPages <T>( GraphServiceClient graphClient, ICollectionPage <T> page) { var allItems = new List <T>(); var pageIterator = PageIterator <T> .CreatePageIterator( graphClient, page, (item) => { // This code executes for each item in the // collection allItems.Add(item); return(true); } ); await pageIterator.IterateAsync(); return(allItems); }
/// <summary> /// Creates the PageIterator with the results of an initial paged request. /// </summary> /// <param name="client">The GraphServiceClient object used to create the NextPageRequest for a delta query.</param> /// <param name="page">A generated implementation of ICollectionPage.</param> /// <param name="callback">A Func delegate that processes type TEntity in the result set and should return false if the iterator should cancel processing.</param> /// <returns>A PageIterator<TEntity> that will process additional result pages based on the rules specified in Func<TEntity,bool> processPageItems</returns> public static PageIterator <TEntity> CreatePageIterator(IBaseClient client, ICollectionPage <TEntity> page, Func <TEntity, bool> callback) { if (page == null) { throw new ArgumentNullException("page"); } if (callback == null) { throw new ArgumentNullException("processPageItems"); } return(new PageIterator <TEntity>() { _client = client, _currentPage = page, _pageItemQueue = new Queue <TEntity>(page), _processPageItemCallback = callback, State = PagingState.NotStarted }); }
/// <summary>Patches missing page context for the given collection and page index.</summary> /// <param name="collection">The collection.</param> /// <param name="pageIndex">The page index.</param> /// <typeparam name="T">The type of values in the collection.</typeparam> /// <exception cref="ArgumentNullException">The value of <paramref name="collection"/> is a null reference.</exception> public static void Patch <T>(ICollectionPage <T> collection, int pageIndex) { if (collection == null) { throw new ArgumentNullException("collection", "Precondition: collection != null"); } collection.PageIndex = pageIndex; if (collection.PageCount > 0) { collection.LastPageIndex = collection.PageCount - 1; if (collection.PageIndex < collection.LastPageIndex) { collection.NextPageIndex = collection.PageIndex + 1; } if (collection.PageIndex > collection.FirstPageIndex) { collection.PreviousPageIndex = collection.PageIndex - 1; } } }
public static string GetNextLink <T>(this ICollectionPage <T> page) { return(page.AdditionalData[NEXT_LINK].ToString()); }
public static string GetDeltaLink <T>(this ICollectionPage <T> page) { return(page.AdditionalData[DELTA_LINK].ToString()); }