more caching, more seo

This commit is contained in:
Tommy Parnell
2019-01-20 17:29:14 -05:00
parent 76f558edc9
commit 93409aadcb
11 changed files with 122 additions and 11 deletions

View File

@@ -12,9 +12,10 @@ namespace TerribleDev.Blog.Web.Controllers
{
public class HomeController : Controller
{
static List<IPost> postsAsList = new BlogFactory().GetAllPosts().OrderByDescending(a=>a.PublishDate).ToList();
static IDictionary<string, IPost> posts = postsAsList.ToDictionary(a=>a.Url);
static IDictionary<int, List<IPost>> postsByPage = postsAsList.Aggregate(new Dictionary<int, List<IPost>>() { [1] = new List<IPost>() }, (accum, item) =>
public static List<IPost> postsAsList = new BlogFactory().GetAllPosts().OrderByDescending(a=>a.PublishDate).ToList();
public static HashSet<string> totalTags = postsAsList.Where(a=>a.tags != null).SelectMany(a => a.tags).ToHashSet();
public static IDictionary<string, IPost> posts = postsAsList.ToDictionary(a=>a.Url);
public static IDictionary<int, List<IPost>> postsByPage = postsAsList.Aggregate(new Dictionary<int, List<IPost>>() { [1] = new List<IPost>() }, (accum, item) =>
{
var highestPage = accum.Keys.Max();
var current = accum[highestPage].Count;
@@ -57,6 +58,7 @@ namespace TerribleDev.Blog.Web.Controllers
}
[Route("{postUrl}")]
[OutputCache(Duration = 31536000, VaryByParam = "postUrl")]
[ResponseCache(Duration = 180)]
public IActionResult Post(string postUrl)
{

View File

@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.SyndicationFeed;
using Microsoft.SyndicationFeed.Rss;
using TerribleDev.Blog.Web.Models;
namespace TerribleDev.Blog.Web.Controllers
{
public class SeoController : Controller
{
public static DateTimeOffset publishDate = DateTimeOffset.UtcNow; // keep publish date in memory so we just return when the server was kicked
public static IEnumerable<SyndicationItem> postsToSyndication = HomeController.postsAsList.Select(a => a.ToSyndicationItem()).ToList();
[Route("/rss")]
[Route("/rss.xml")]
[ResponseCache(Duration = 7200)]
[OutputCache(Duration = 86400)]
public async Task Rss()
{
Response.StatusCode = 200;
Response.ContentType = "text/xml";
using (XmlWriter xmlWriter = XmlWriter.Create(this.Response.Body, new XmlWriterSettings() { Async = true, Indent = false, Encoding = Encoding.UTF8 }))
{
var writer = new RssFeedWriter(xmlWriter);
await writer.WriteTitle("The Ramblings of TerribleDev");
await writer.WriteValue("link", "https://blog.terribledev.io");
await writer.WriteDescription("My name is Tommy Parnell. I usually go by TerribleDev on the internets. These are just some of my writings and rants about the software space.");
foreach (var item in postsToSyndication)
{
await writer.Write(item);
}
await xmlWriter.FlushAsync();
}
}
[Route("/sitemap.xml")]
[ResponseCache(Duration = 7200)]
[OutputCache(Duration = 86400)]
public void SiteMap()
{
Response.StatusCode = 200;
Response.ContentType = "text/xml";
var ser = new XmlSerializer(typeof(SiteMapRoot));
var sitemap = new SiteMapRoot()
{
Urls = HomeController.postsAsList.Select(a => new SiteMapItem() { LastModified = DateTime.UtcNow, Location = $"https://blog.terribledev.io/{a.Url}" }).ToList()
};
ser.Serialize(this.Response.Body, sitemap);
}
}
}

View File

@@ -0,0 +1,23 @@
using Microsoft.SyndicationFeed;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TerribleDev.Blog.Web.Models;
namespace TerribleDev.Blog.Web
{
public static class IPostExtensions
{
public static SyndicationItem ToSyndicationItem(this IPost x)
{
return new SyndicationItem()
{
Title = x.Title,
Description = x.ContentPlain,
Id = $"https://blog.terribledev.io/{x.Url}",
Published = x.PublishDate
};
}
}
}

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TerribleDev.Blog.Web.Extensions
namespace TerribleDev.Blog.Web
{
public static class StringExtension
{

View File

@@ -6,7 +6,6 @@ using System.IO;
using TerribleDev.Blog.Web.Models;
using YamlDotNet.Serialization;
using Microsoft.AspNetCore.Html;
using TerribleDev.Blog.Web.Extensions;
using Markdig;
namespace TerribleDev.Blog.Web
@@ -40,7 +39,7 @@ namespace TerribleDev.Blog.Web
var markdownText = string.Join("", splitFile.Skip(1));
var pipeline = new MarkdownPipelineBuilder().UseEmojiAndSmiley().Build();
var postContent = Markdown.ToHtml(markdownText, pipeline);
var postContentPlain = Markdown.ToPlainText(markdownText, pipeline);
var postContentPlain = String.Join("", Markdown.ToPlainText(markdownText, pipeline).Split("<!-- more -->"));
var postSettings = ParseYaml(ymlRaw);
var resolvedUrl = !string.IsNullOrWhiteSpace(postSettings.permalink) ? postSettings.permalink : fileName.Split('.')[0].Replace(' ', '-').WithoutSpecialCharacters();
var summary = postContent.Split("<!-- more -->")[0];

View File

@@ -12,7 +12,7 @@ namespace TerribleDev.Blog.Web.Models
string Url { get; set; }
string Title { get; set; }
HtmlString Summary { get; set; }
DateTimeOffset PublishDate { get; set; }
DateTime PublishDate { get; set; }
HtmlString Content { get; set; }
string ContentPlain { get; set; }
string SummaryPlain { get; set; }

View File

@@ -8,7 +8,7 @@ namespace TerribleDev.Blog.Web.Models
{
public string Url { get; set; }
public string Title { get; set; }
public DateTimeOffset PublishDate { get; set; }
public DateTime PublishDate { get; set; }
public HtmlString Content { get; set; }
public HtmlString Summary { get; set; }
public string ContentPlain { get; set; }

View File

@@ -8,8 +8,8 @@ namespace TerribleDev.Blog.Web.Models
public List<string> tags { get; set; }
public string title { get; set; }
public string permalink { get; set; }
public DateTimeOffset date { get; set; }
public DateTimeOffset updated { get; set; }
public DateTime date { get; set; }
public DateTime updated { get; set; }
public string id { get; set; }
public string thumbnail_image { get; set; }
public string thumbnailImage { get; set; }

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace TerribleDev.Blog.Web.Models
{
[XmlRoot("urlset")]
public class SiteMapRoot
{
[XmlElement("url")]
public List<SiteMapItem> Urls { get; set; }
}
public class SiteMapItem
{
[XmlElement("loc")]
public string Location { get; set; }
[XmlElement("lastmod")]
public DateTime LastModified { get; set; }
}
}

View File

@@ -39,6 +39,7 @@ namespace TerribleDev.Blog.Web
.AddCacheTagHelper()
.AddRazorViewEngine()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddOutputCaching();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@@ -80,7 +81,8 @@ namespace TerribleDev.Blog.Web
"public,max-age=" + cacheTime;
}
});
app.UseRewriter(new Microsoft.AspNetCore.Rewrite.RewriteOptions().AddRedirect("(.*[^/])$", "$1/", 301));
app.UseRewriter(new Microsoft.AspNetCore.Rewrite.RewriteOptions().AddRedirect("(.*[^/|.xml])$", "$1/", 301));
app.UseOutputCaching();
app.UseMvc();
}
}

View File

@@ -27,6 +27,8 @@
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.0" />
<PackageReference Include="YamlDotNet" Version="5.3.0" />
<PackageReference Include="HardHat" Version="2.0.0" />
<PackageReference Include="Microsoft.SyndicationFeed.ReaderWriter" Version="1.0.2" />
<PackageReference Include="WebEssentials.AspNetCore.OutputCaching" Version="1.0.16" />
</ItemGroup>