public async Task <BlobContent> ReadBlobContentAsync(long tenantId, long elementId, long blobSetId, string blobLabel)
        {
            CarouselElementSettings settings = await _elementRepository.ReadElementSettingsAsync(tenantId, elementId);

            if (settings == null)
            {
                return(null);
            }

            CarouselSlide slide = settings.Slides.Where(s => s.BlobSetId == blobSetId).FirstOrDefault();

            if (slide == null)
            {
                return(null);
            }

            long?blobId = GetBlobId(slide, blobLabel);

            if (blobId == null)
            {
                return(null);
            }

            return(await _storageService.ReadBlobContentAsync(tenantId, blobId.Value, string.Format(CarouselImagePath, elementId)));
        }
        public async Task <IElementView <CarouselElementSettings, CarouselElementContent> > ReadElementViewAsync(long tenantId, long elementId, IPageContext context)
        {
            // Get element settings
            CarouselElementSettings settings = await _elementRepository.ReadElementSettingsAsync(tenantId, elementId);

            if (settings == null)
            {
                return(null);
            }

            // Get details of preview images
            IEnumerable <long> previewImageBlobIds = settings.Slides.Select(s => s.PreviewImageBlobId);
            IEnumerable <Blob> previewImageBlobs   = await _storageService.ListBlobsAsync(tenantId, previewImageBlobIds);

            IDictionary <long, BlobImage> previewImageBlobsById = previewImageBlobs.ToDictionary(b => b.BlobId, b => (BlobImage)b);

            // Get details of pages linked to from carousel slide buttons
            IEnumerable <long> buttonPageIds = settings.Slides.Where(s => s.ButtonPageId.HasValue).Select(s => s.ButtonPageId.Value).Distinct();
            IEnumerable <Page> buttonPages   = await _pageService.ListPagesAsync(tenantId, buttonPageIds);

            IDictionary <long, string>         buttonTextByPageId = settings.Slides.Where(s => s.ButtonPageId.HasValue && s.ButtonText != null).ToDictionary(s => s.ButtonPageId.Value, s => s.ButtonText);
            IDictionary <long, CarouselButton> buttonsByPageId    = buttonPages.ToDictionary(p => p.PageId, p => new CarouselButton {
                Home = !p.ParentPageId.HasValue, Name = p.Name, PageId = p.PageId, ButtonText = buttonTextByPageId.ContainsKey(p.PageId) ? buttonTextByPageId[p.PageId] : null
            });

            // Construct list of slides for carousel content
            IDictionary <long, CarouselContentSlide> slides = settings
                                                              .Slides
                                                              .Where(s => previewImageBlobsById.ContainsKey(s.PreviewImageBlobId))
                                                              .Select(s => new CarouselContentSlide
            {
                BlobSetId     = s.BlobSetId,
                PreviewWidth  = previewImageBlobsById[s.PreviewImageBlobId].Width,
                PreviewHeight = previewImageBlobsById[s.PreviewImageBlobId].Height,
                Button        = s.ButtonPageId.HasValue && buttonsByPageId.ContainsKey(s.ButtonPageId.Value) ? buttonsByPageId[s.ButtonPageId.Value] : null
            })
                                                              .ToDictionary(s => s.BlobSetId, s => s);

            // Construct element content
            CarouselElementContent content = new CarouselElementContent
            {
                Slides = slides
            };

            // Return element view
            return(new ElementView <CarouselElementSettings, CarouselElementContent>
            {
                Settings = settings,
                Content = content
            });
        }