using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using RMuseum.DbContext; using RMuseum.Models.Ganjoor; using RMuseum.Models.Ganjoor.ViewModels; using RSecurityBackend.Models.Generic; using RSecurityBackend.Models.Image; using RSecurityBackend.Services; using System; using System.IO; using System.Linq; using System.Threading.Tasks; namespace RMuseum.Services.Implementation { /// /// ganjoor.net banners service /// public class SiteBannersService : ISiteBannersService { /// /// Add site banner /// /// /// /// /// /// /// public async Task> AddSiteBanner(Stream imageStream, string fileName, string alternateText, string targetUrl, bool active) { RServiceResult image = await _imageFileService.Add(null, imageStream, fileName, "SiteBanners"); if (!string.IsNullOrEmpty(image.ExceptionString)) { return new RServiceResult(null, image.ExceptionString); } GanjoorSiteBanner banner = new GanjoorSiteBanner() { RImage = image.Result, AlternateText = alternateText, TargetUrl = targetUrl, Active = active }; _context.GanjoorSiteBanners.Add(banner); await _context.SaveChangesAsync(); await CleanBannersCache(); return new RServiceResult ( new GanjoorSiteBannerViewModel() { Id = banner.Id, ImageUrl = $"api/rimages/{banner.RImageId}.jpg", AlternateText = banner.AlternateText, TargetUrl = banner.TargetUrl, Active = banner.Active } ); } /// /// modify site banner /// /// /// /// /// /// public async Task> ModifySiteBanner(int id, string alternateText, string targetUrl, bool active) { GanjoorSiteBanner target = await _context.GanjoorSiteBanners.Where(b => b.Id == id).SingleOrDefaultAsync(); if (target == null) return new RServiceResult(false);//not found target.AlternateText = alternateText; target.TargetUrl = targetUrl; target.Active = active; _context.GanjoorSiteBanners.Update(target); await _context.SaveChangesAsync(); await CleanBannersCache(); return new RServiceResult(true); } /// /// delete site banner /// /// /// public async Task> DeleteSiteBanner(int id) { GanjoorSiteBanner target = await _context.GanjoorSiteBanners.Where(b => b.Id == id).SingleOrDefaultAsync(); if (target == null) return new RServiceResult(false);//not found _context.GanjoorSiteBanners.Remove(target); await _context.SaveChangesAsync(); await CleanBannersCache(); return new RServiceResult(true); } /// /// get site banners /// /// public async Task> GetSiteBanners() { return new RServiceResult( await _context.GanjoorSiteBanners .Select(b => new GanjoorSiteBannerViewModel() { Id = b.Id, ImageUrl = $"api/rimages/{b.RImageId}.jpg", AlternateText = b.AlternateText, TargetUrl = b.TargetUrl, Active = b.Active }).ToArrayAsync() ); } private const string _cacheKeyForIdSet = "SiteBannersService::GetARandomActiveSiteBanner::idSet"; private static string GetBannerCacheKey(int bannerId) { return $"SiteBannersService::BannerCacheKey::{bannerId}"; } private async Task CleanBannersCache() { int[] idSet = await _context.GanjoorSiteBanners.Select(b => b.Id).ToArrayAsync(); foreach (int id in idSet) { var cacheKey = GetBannerCacheKey(id); if (_memoryCache.TryGetValue(id, out GanjoorSiteBannerViewModel o)) { _memoryCache.Remove(id); } } if (_memoryCache.TryGetValue(_cacheKeyForIdSet, out idSet)) { _memoryCache.Remove(_cacheKeyForIdSet); } } /// /// get a random site banner /// /// public async Task> GetARandomActiveSiteBanner() { if (!_memoryCache.TryGetValue(_cacheKeyForIdSet, out int[] idSet)) { idSet = await _context.GanjoorSiteBanners.Where(b => b.Active == true).Select(b => b.Id).ToArrayAsync(); _memoryCache.Set(_cacheKeyForIdSet, idSet, TimeSpan.FromHours(1)); } if (idSet.Length == 0) return new RServiceResult(null);//no active banner Random rnd = new Random(DateTime.Now.Millisecond); int id = idSet[rnd.Next(0, idSet.Length)]; var cachKey = GetBannerCacheKey(id); if (!_memoryCache.TryGetValue(cachKey, out GanjoorSiteBannerViewModel banner)) { banner = await _context.GanjoorSiteBanners .Where(b => b.Id == id) .Select(b => new GanjoorSiteBannerViewModel() { Id = b.Id, ImageUrl = $"api/rimages/{b.RImageId}.jpg", AlternateText = b.AlternateText, TargetUrl = b.TargetUrl, Active = b.Active }) .AsNoTracking() .SingleAsync(); _memoryCache.Set(cachKey, banner, TimeSpan.FromHours(1)); } return new RServiceResult(banner); } /// /// Database Context /// protected readonly RMuseumDbContext _context; /// /// Image File Service /// protected readonly IImageFileService _imageFileService; /// /// IMemoryCache /// protected readonly IMemoryCache _memoryCache; /// /// constructor /// /// /// /// public SiteBannersService(RMuseumDbContext context, IImageFileService imageFileService, IMemoryCache memoryCache) { _context = context; _imageFileService = imageFileService; _memoryCache = memoryCache; } } }