Skip to content

Commit cb71cd9

Browse files
committed
feat: implement output caching for various endpoints and introduce BasePageModel for cache management
1 parent 60c14fe commit cb71cd9

14 files changed

Lines changed: 131 additions & 30 deletions

Web/Extensions/EndpointExtensions.cs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@
88
namespace Web.Extensions;
99

1010
public static class EndpointExtensions
11-
{
12-
public static void MapSitemapEndpoint(this WebApplication app)
11+
{ public static void MapSitemapEndpoint(this WebApplication app)
1312
{
1413
app.MapGet("/sitemap.xml", async (HttpContext context, IContentService contentService) =>
1514
{
15+
// Enable output caching for sitemap
16+
context.Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue
17+
{
18+
Public = true,
19+
MaxAge = TimeSpan.FromHours(1)
20+
};
1621
// Define the XML namespace for the sitemap
1722
XNamespace ns = "http://www.sitemaps.org/schemas/sitemap/0.9";
1823

@@ -106,13 +111,21 @@ public static void MapSitemapEndpoint(this WebApplication app)
106111

107112
// Return the XML document as a string
108113
return sitemap.ToString();
109-
});
110-
}
111-
112-
public static void MapRssFeedEndpoint(this WebApplication app)
114+
})
115+
.CacheOutput(policy => policy
116+
.Expire(TimeSpan.FromHours(1))
117+
.SetVaryByHost(true)
118+
.Tag("sitemap"));
119+
} public static void MapRssFeedEndpoint(this WebApplication app)
113120
{
114121
app.MapGet("/feed.rss", async (HttpContext context, IContentService contentService) =>
115-
{ // Create the RSS feed XML document
122+
{
123+
// Enable output caching for RSS feed
124+
context.Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue
125+
{
126+
Public = true,
127+
MaxAge = TimeSpan.FromMinutes(30)
128+
};// Create the RSS feed XML document
116129
var rss = new XDocument(
117130
new XDeclaration("1.0", "utf-8", null),
118131
new XProcessingInstruction("xml-stylesheet", "type=\"text/xsl\" href=\"/xsl/rss.xsl\""),
@@ -173,6 +186,10 @@ public static void MapRssFeedEndpoint(this WebApplication app)
173186

174187
// Return the XML document as a string
175188
return rss.ToString();
176-
});
189+
})
190+
.CacheOutput(policy => policy
191+
.Expire(TimeSpan.FromMinutes(30))
192+
.SetVaryByHost(true)
193+
.Tag("rss"));
177194
}
178195
}

Web/Pages/About.cshtml.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
namespace Web.Pages;
44

5-
public class AboutModel : PageModel
5+
public class AboutModel : BasePageModel
66
{
7+
// Override cache duration for static pages - cache for 1 hour
8+
protected override int CacheDurationSeconds => 3600;
9+
710
public void OnGet()
811
{
912
}

Web/Pages/BasePageModel.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using Microsoft.AspNetCore.Mvc.Filters;
3+
using Microsoft.AspNetCore.Mvc.RazorPages;
4+
using Microsoft.AspNetCore.OutputCaching;
5+
6+
namespace Web.Pages;
7+
8+
[OutputCache]
9+
public abstract class BasePageModel : PageModel
10+
{
11+
/// <summary>
12+
/// The default output cache duration for dynamic pages
13+
/// </summary>
14+
protected virtual int CacheDurationSeconds => 300; // 5 minutes by default
15+
16+
/// <summary>
17+
/// Whether the page allows caching by default
18+
/// </summary>
19+
protected virtual bool AllowCaching => true;
20+
21+
/// <summary>
22+
/// Configure output caching for the page
23+
/// </summary>
24+
public override void OnPageHandlerExecuting(PageHandlerExecutingContext context)
25+
{
26+
base.OnPageHandlerExecuting(context);
27+
28+
if (AllowCaching && HttpContext.Request.Method == "GET")
29+
{
30+
// Set cache headers
31+
var headers = HttpContext.Response.GetTypedHeaders();
32+
headers.CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue
33+
{
34+
Public = true,
35+
MaxAge = TimeSpan.FromSeconds(CacheDurationSeconds)
36+
};
37+
}
38+
}
39+
40+
/// <summary>
41+
/// Clear the output cache for this page
42+
/// </summary>
43+
protected async Task InvalidateCache()
44+
{
45+
var outputCacheStore = HttpContext.RequestServices.GetRequiredService<IOutputCacheStore>();
46+
await outputCacheStore.EvictByTagAsync(GetType().FullName!, default);
47+
}
48+
}

Web/Pages/Contribute.cshtml.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
namespace Web.Pages;
44

5-
public class ContributeModel : PageModel
5+
public class ContributeModel : BasePageModel
66
{
7+
// Override cache duration for static content - cache for 1 hour
8+
protected override int CacheDurationSeconds => 3600;
9+
710
public void OnGet()
811
{
912
}

Web/Pages/Index.cshtml.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55

66
namespace Web.Pages;
77

8-
public class IndexModel : PageModel
8+
public class IndexModel : BasePageModel
99
{
1010
private readonly ILogger<IndexModel> _logger;
1111
private readonly IContentService _contentService;
1212

13+
// Override cache duration for home page - cache for 10 minutes
14+
protected override int CacheDurationSeconds => 600;
15+
1316
public List<TipModel> RecentTips { get; set; } = new();
1417
public List<string> Categories { get; set; } = new();
1518
public List<string> PopularTags { get; set; } = new();

Web/Pages/Privacy.cshtml.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33

44
namespace Web.Pages;
55

6-
public class PrivacyModel : PageModel
6+
public class PrivacyModel : BasePageModel
77
{
88
private readonly ILogger<PrivacyModel> _logger;
99
private readonly IConfiguration _configuration;
10+
11+
// Override cache duration for static pages - cache for 1 hour
12+
protected override int CacheDurationSeconds => 3600;
1013

1114
public PrivacyModel(ILogger<PrivacyModel> logger, IConfiguration configuration)
1215
{

Web/Pages/Terms.cshtml.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
namespace Web.Pages;
44

5-
public class TermsModel : PageModel
5+
public class TermsModel : BasePageModel
66
{
7+
// Override cache duration for static pages - cache for 1 hour
8+
protected override int CacheDurationSeconds => 3600;
9+
710
public void OnGet()
811
{
912
}

Web/Pages/Tips/Category.cshtml.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55

66
namespace Web.Pages.Tips;
77

8-
public class CategoryModel : PageModel
8+
public class CategoryModel : BasePageModel
99
{
1010
private readonly IContentService _contentService;
1111
private readonly ILogger<CategoryModel> _logger;
12+
13+
// Override cache duration for category pages - cache for 5 minutes
14+
protected override int CacheDurationSeconds => 300;
1215

1316
public CategoryModel(IContentService contentService, ILogger<CategoryModel> logger)
1417
{

Web/Pages/Tips/Details.cshtml.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55

66
namespace Web.Pages.Tips;
77

8-
public class DetailsModel : PageModel
8+
public class DetailsModel : BasePageModel
99
{
1010
private readonly IContentService _contentService;
1111
private readonly ILogger<DetailsModel> _logger;
12+
13+
// Override cache duration for individual tips - cache for 1 hour since they change less frequently
14+
protected override int CacheDurationSeconds => 3600;
1215

1316
public DetailsModel(IContentService contentService, ILogger<DetailsModel> logger)
1417
{

Web/Pages/Tips/Index.cshtml.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55

66
namespace Web.Pages.Tips;
77

8-
public class IndexModel : PageModel
8+
public class IndexModel : BasePageModel
99
{
1010
private readonly IContentService _contentService;
1111
private readonly ILogger<IndexModel> _logger;
12+
13+
// Override cache duration for tips list - cache for 5 minutes
14+
protected override int CacheDurationSeconds => 300;
1215

1316
public IndexModel(IContentService contentService, ILogger<IndexModel> logger)
1417
{

0 commit comments

Comments
 (0)