Пример #1
0
    public async Task <IActionResult> Avatar([FromServices] IBlogCache cache)
    {
        var fallbackImageFile = Path.Join($"{_env.WebRootPath}", "images", "default-avatar.png");

        try
        {
            var bytes = await cache.GetOrCreateAsync(CacheDivision.General, "avatar", async _ =>
            {
                _logger.LogTrace("Avatar not on cache, getting new avatar image...");

                var data = await _mediator.Send(new GetAssetDataQuery(AssetId.AvatarBase64));
                if (string.IsNullOrWhiteSpace(data))
                {
                    return(null);
                }

                var avatarBytes = Convert.FromBase64String(data);
                return(avatarBytes);
            });

            if (null == bytes)
            {
                return(PhysicalFile(fallbackImageFile, "image/png"));
            }

            return(File(bytes, "image/png"));
        }
        catch (FormatException e)
        {
            _logger.LogError($"Error {nameof(Avatar)}(), Invalid Base64 string", e);
            return(PhysicalFile(fallbackImageFile, "image/png"));
        }
    }
Пример #2
0
        public async Task Invoke(
            HttpContext httpContext,
            IBlogConfig blogConfig,
            IBlogCache cache,
            IOptions <AppSettings> settings,
            IRepository <PostEntity> postRepo,
            IRepository <PageEntity> pageRepo)
        {
            if (httpContext.Request.Path == "/sitemap.xml")
            {
                var xml = await cache.GetOrCreateAsync(CacheDivision.General, "sitemap", async _ =>
                {
                    var url  = Helper.ResolveRootUrl(httpContext, blogConfig.GeneralSettings.CanonicalPrefix, true);
                    var data = await GetSiteMapData(url, settings.Value.SiteMap, postRepo, pageRepo);
                    return(data);
                });

                httpContext.Response.ContentType = "text/xml";
                await httpContext.Response.WriteAsync(xml, httpContext.RequestAborted);
            }
            else
            {
                await _next(httpContext);
            }
        }
Пример #3
0
        public async Task <IActionResult> Index(string slug)
        {
            if (string.IsNullOrWhiteSpace(slug))
            {
                return(BadRequest());
            }

            var page = await _cache.GetOrCreateAsync(CacheDivision.Page, slug.ToLower(), async entry =>
            {
                entry.SlidingExpiration = TimeSpan.FromMinutes(AppSettings.CacheSlidingExpirationMinutes["Page"]);

                var p = await _customPageService.GetAsync(slug);
                return(p);
            });

            if (page == null)
            {
                Logger.LogWarning($"Page not found. {nameof(slug)}: '{slug}'");
                return(NotFound());
            }

            if (!page.IsPublished)
            {
                return(NotFound());
            }

            return(View(page));
        }
Пример #4
0
    public async Task <IActionResult> OnGetAsync(string routeName)
    {
        if (string.IsNullOrWhiteSpace(routeName))
        {
            return(NotFound());
        }

        var pageSize = _blogConfig.ContentSettings.PostListPageSize;
        var cat      = await _mediator.Send(new GetCategoryByRouteCommand(routeName));

        if (cat is null)
        {
            return(NotFound());
        }

        ViewData["CategoryDisplayName"] = cat.DisplayName;
        ViewData["CategoryRouteName"]   = cat.RouteName;
        ViewData["CategoryDescription"] = cat.Note;

        var postCount = await _cache.GetOrCreateAsync(CacheDivision.PostCountCategory, cat.Id.ToString(),
                                                      _ => _mediator.Send(new CountPostQuery(CountType.Category, cat.Id)));

        var postList = await _mediator.Send(new ListPostsQuery(pageSize, P, cat.Id));

        Posts = new(postList, P, pageSize, postCount);
        return(Page());
    }
Пример #5
0
 public Task <IReadOnlyList <Category> > Handle(GetCategoriesQuery request, CancellationToken cancellationToken)
 {
     return(_cache.GetOrCreateAsync(CacheDivision.General, "allcats", async entry =>
     {
         entry.SlidingExpiration = TimeSpan.FromHours(1);
         var list = await _catRepo.SelectAsync(Category.EntitySelector);
         return list;
     }));
 }
Пример #6
0
 public Task <IReadOnlyList <Category> > GetAll()
 {
     return(_cache.GetOrCreateAsync(CacheDivision.General, "allcats", async entry =>
     {
         entry.SlidingExpiration = TimeSpan.FromHours(1);
         var list = await _catRepo.SelectAsync(_categorySelector);
         return list;
     }));
 }
Пример #7
0
        public async Task <PostSlug> GetAsync(PostSlugInfo slugInfo)
        {
            var date = new DateTime(slugInfo.Year, slugInfo.Month, slugInfo.Day);
            var spec = new PostSpec(date, slugInfo.Slug);

            var pid = await _postRepository.SelectFirstOrDefaultAsync(spec, p => p.Id);

            if (pid == Guid.Empty)
            {
                return(null);
            }

            var psm = await _cache.GetOrCreateAsync(CacheDivision.Post, $"{pid}", async entry =>
            {
                entry.SlidingExpiration = TimeSpan.FromMinutes(AppSettings.CacheSlidingExpirationMinutes["Post"]);

                var postSlugModel = await _postRepository.SelectFirstOrDefaultAsync(spec, post => new PostSlug
                {
                    Title           = post.Title,
                    ContentAbstract = post.ContentAbstract,
                    PubDateUtc      = post.PubDateUtc.GetValueOrDefault(),

                    Categories = post.PostCategory.Select(pc => pc.Category).Select(p => new Category
                    {
                        DisplayName = p.DisplayName,
                        RouteName   = p.RouteName
                    }).ToArray(),

                    RawPostContent = post.PostContent,
                    Hits           = post.PostExtension.Hits,
                    Likes          = post.PostExtension.Likes,

                    Tags = post.PostTag.Select(pt => pt.Tag)
                           .Select(p => new Tag
                    {
                        NormalizedName = p.NormalizedName,
                        DisplayName    = p.DisplayName
                    }).ToArray(),
                    Id                  = post.Id,
                    CommentEnabled      = post.CommentEnabled,
                    ExposedToSiteMap    = post.ExposedToSiteMap,
                    LastModifyOnUtc     = post.LastModifiedUtc,
                    ContentLanguageCode = post.ContentLanguageCode,
                    CommentCount        = post.Comment.Count(c => c.IsApproved)
                });

                if (null != postSlugModel)
                {
                    postSlugModel.RawPostContent = AddLazyLoadToImgTag(postSlugModel.RawPostContent);
                }

                return(postSlugModel);
            });

            return(psm);
        }
        public async Task <IActionResult> Atom([FromServices] IBlogCache cache)
        {
            return(await cache.GetOrCreateAsync(CacheDivision.General, "atom", async entry =>
            {
                entry.SlidingExpiration = TimeSpan.FromHours(1);

                var xml = await _syndicationService.GetAtomData();
                return Content(xml, "text/xml");
            }));
        }
Пример #9
0
        public async Task <IActionResult> Rss(string routeName = null)
        {
            bool hasRoute = !string.IsNullOrWhiteSpace(routeName);
            var  route    = hasRoute ? routeName.ToLower().Trim() : null;

            return(await _cache.GetOrCreateAsync(
                       hasRoute?CacheDivision.PostCountCategory : CacheDivision.General, route ?? "rss", async entry =>
            {
                entry.SlidingExpiration = TimeSpan.FromHours(1);

                var xml = await _syndicationService.GetRssStringAsync(routeName);
                if (string.IsNullOrWhiteSpace(xml))
                {
                    return (IActionResult)NotFound();
                }

                return Content(xml, "text/xml");
            }));
        }
Пример #10
0
 public async Task <IActionResult> SiteMap([FromServices] IBlogConfig blogConfig, [FromServices] IBlogCache cache)
 {
     return(await cache.GetOrCreateAsync(CacheDivision.General, "sitemap", async entry =>
     {
         var url = ResolveRootUrl(blogConfig);
         var bytes = await _searchService.GetSiteMapStreamArrayAsync(url);
         var xmlContent = Encoding.UTF8.GetString(bytes);
         return Content(xmlContent, "text/xml");
     }));
 }
Пример #11
0
        public async Task <IActionResult> SiteMap([FromServices] IBlogConfig blogConfig, [FromServices] IBlogCache cache)
        {
            return(await cache.GetOrCreateAsync(CacheDivision.General, "sitemap", async _ =>
            {
                var url = Helper.ResolveRootUrl(HttpContext, blogConfig.GeneralSettings.CanonicalPrefix, true);
                var bytes = await _searchService.GetSiteMapStreamArrayAsync(url);
                var xmlContent = Encoding.UTF8.GetString(bytes);

                return Content(xmlContent, "text/xml");
            }));
        }
Пример #12
0
    public async Task OnGet(int p = 1)
    {
        var pagesize = _blogConfig.ContentSettings.PostListPageSize;
        var posts    = await _mediator.Send(new ListPostsQuery(pagesize, p));

        var count = await _cache.GetOrCreateAsync(CacheDivision.General, "postcount", _ => _mediator.Send(new CountPostQuery(CountType.Public)));

        var list = new StaticPagedList <PostDigest>(posts, p, pagesize, count);

        Posts = list;
    }
Пример #13
0
 public Task <IReadOnlyList <Category> > GetAllAsync()
 {
     return(_cache.GetOrCreateAsync(CacheDivision.General, "allcats", async entry =>
     {
         var list = await _categoryRepository.SelectAsync(c => new Category
         {
             Id = c.Id,
             DisplayName = c.DisplayName,
             RouteName = c.RouteName,
             Note = c.Note
         });
         return list;
     }));
 }
Пример #14
0
        public async Task <IActionResult> Rss([FromServices] IBlogCache cache, string routeName = null)
        {
            bool hasRoute = !string.IsNullOrWhiteSpace(routeName);
            var  route    = hasRoute ? routeName.ToLower().Trim() : null;

            return(await cache.GetOrCreateAsync(
                       hasRoute?CacheDivision.PostCountCategory : CacheDivision.General, route ?? "rss", async entry =>
            {
                entry.SlidingExpiration = TimeSpan.FromHours(1);

                var bytes = await _syndicationService.GetRssStreamDataAsync(routeName);
                var xmlContent = Encoding.UTF8.GetString(bytes);
                return Content(xmlContent, "text/xml");
            }));
        }
Пример #15
0
 public Task <IReadOnlyList <Category> > GetAllAsync()
 {
     return(_cache.GetOrCreateAsync(CacheDivision.General, "allcats", async entry =>
     {
         entry.SlidingExpiration = TimeSpan.FromHours(1);
         var list = await _catRepo.SelectAsync(c => new Category
         {
             Id = c.Id,
             DisplayName = c.DisplayName,
             RouteName = c.RouteName,
             Note = c.Note
         });
         return list;
     }));
 }
Пример #16
0
        public async Task Invoke(HttpContext httpContext, IBlogConfig blogConfig, IBlogCache cache, ISiteMapWriter siteMapWriter)
        {
            if (httpContext.Request.Path == "/sitemap.xml")
            {
                var xml = await cache.GetOrCreateAsync(CacheDivision.General, "sitemap", async _ =>
                {
                    var url  = Helper.ResolveRootUrl(httpContext, blogConfig.GeneralSettings.CanonicalPrefix, true);
                    var data = await siteMapWriter.GetSiteMapData(url);
                    return(data);
                });

                httpContext.Response.ContentType = "text/xml";
                await httpContext.Response.WriteAsync(xml);
            }
            else
            {
                await _next(httpContext);
            }
        }
Пример #17
0
        public async Task <IViewComponentResult> InvokeAsync()
        {
            try
            {
                var menus = await _cache.GetOrCreateAsync(CacheDivision.General, "menu", async entry =>
                {
                    entry.SlidingExpiration = TimeSpan.FromMinutes(20);

                    var items = await _menuService.GetAllAsync();
                    return(items);
                });

                return(View(menus));
            }
            catch (Exception e)
            {
                return(Content(e.Message));
            }
        }
Пример #18
0
        public async Task <IActionResult> Page(string slug)
        {
            if (string.IsNullOrWhiteSpace(slug))
            {
                return(BadRequest());
            }

            var page = await _cache.GetOrCreateAsync(CacheDivision.Page, slug.ToLower(), async entry =>
            {
                entry.SlidingExpiration = TimeSpan.FromMinutes(_settings.CacheSlidingExpirationMinutes["Page"]);

                var p = await _pageService.GetAsync(slug);
                return(p);
            });

            if (page is null || !page.IsPublished)
            {
                return(NotFound());
            }
            return(View(page));
        }
Пример #19
0
    public async Task <IActionResult> OnGet(string normalizedName)
    {
        var tagResponse = await _mediator.Send(new GetTagQuery(normalizedName));

        if (tagResponse is null)
        {
            return(NotFound());
        }

        var pagesize = _blogConfig.ContentSettings.PostListPageSize;
        var posts    = await _mediator.Send(new ListByTagQuery(tagResponse.Id, pagesize, P));

        var count = await _cache.GetOrCreateAsync(CacheDivision.PostCountTag, tagResponse.Id.ToString(), _ => _mediator.Send(new CountPostQuery(CountType.Tag, tagId: tagResponse.Id)));

        ViewData["TitlePrefix"] = tagResponse.DisplayName;

        var list = new StaticPagedList <PostDigest>(posts, P, pagesize, count);

        Posts = list;

        return(Page());
    }
Пример #20
0
    public async Task <Post> Handle(GetPostBySlugQuery request, CancellationToken cancellationToken)
    {
        var date = new DateTime(request.Slug.Year, request.Slug.Month, request.Slug.Day);

        // Try to find by checksum
        var slugCheckSum = Helper.ComputeCheckSum($"{request.Slug.Slug}#{date:yyyyMMdd}");
        ISpecification <PostEntity> spec = new PostSpec(slugCheckSum);

        var pid = await _postRepo.SelectFirstOrDefaultAsync(spec, p => p.Id);

        if (pid == Guid.Empty)
        {
            // Post does not have a checksum, fall back to old method
            spec = new PostSpec(date, request.Slug.Slug);
            pid  = await _postRepo.SelectFirstOrDefaultAsync(spec, x => x.Id);

            if (pid == Guid.Empty)
            {
                return(null);
            }

            // Post is found, fill it's checksum so that next time the query can be run against checksum
            var p = await _postRepo.GetAsync(pid);

            p.HashCheckSum = slugCheckSum;

            await _postRepo.UpdateAsync(p);
        }

        var psm = await _cache.GetOrCreateAsync(CacheDivision.Post, $"{pid}", async entry =>
        {
            entry.SlidingExpiration = TimeSpan.FromMinutes(_settings.CacheSlidingExpirationMinutes["Post"]);

            var post = await _postRepo.SelectFirstOrDefaultAsync(spec, Post.EntitySelector);
            return(post);
        });

        return(psm);
    }
Пример #21
0
    public async Task <IActionResult> OnGetAsync(string slug)
    {
        if (string.IsNullOrWhiteSpace(slug))
        {
            return(BadRequest());
        }

        var page = await _cache.GetOrCreateAsync(CacheDivision.Page, slug.ToLower(), async entry =>
        {
            entry.SlidingExpiration = TimeSpan.FromMinutes(_settings.CacheSlidingExpirationMinutes["Page"]);

            var p = await _mediator.Send(new GetPageBySlugQuery(slug));
            return(p);
        });

        if (page is null || !page.IsPublished)
        {
            return(NotFound());
        }

        BlogPage = page;
        return(Page());
    }
Пример #22
0
        public async Task <IActionResult> Css()
        {
            try
            {
                var css = await _cache.GetOrCreateAsync(CacheDivision.General, "theme", async entry =>
                {
                    entry.SlidingExpiration = TimeSpan.FromMinutes(20);

                    // Fall back to default theme for migration
                    if (_blogConfig.GeneralSettings.ThemeId == 0)
                    {
                        _blogConfig.GeneralSettings.ThemeId = 1;
                        await _blogConfig.SaveAsync(_blogConfig.GeneralSettings);
                    }

                    var data = await _themeService.GetStyleSheet(_blogConfig.GeneralSettings.ThemeId);
                    return(data);
                });

                if (css == null)
                {
                    return(NotFound());
                }

                var uCss = Uglify.Css(css);
                if (uCss.HasErrors)
                {
                    return(Conflict(uCss.Errors));
                }

                return(Content(uCss.Code, "text/css"));
            }
            catch (InvalidDataException e)
            {
                return(Conflict(e.Message));
            }
        }