fix: restore Sitemap as Razor Page for search engine compatibility
TaxBaik CI/CD / build-and-deploy (push) Has been cancelled
TaxBaik CI/CD / build-and-deploy (push) Has been cancelled
Problem: - SitemapEndpoint (FastEndpoints) creates /api/sitemap.xml - robots.txt references /taxbaik/sitemap.xml - Path mismatch breaks search engine crawling Solution: - Restore Sitemap.cshtml (Razor Page) - Restore Sitemap.cshtml.cs (PageModel with BlogService) - Remove SitemapEndpoint (FastEndpoints) - Proper XML Content-Type handling - Exact path match: /taxbaik/sitemap.xml Why Razor Page? - Razor Pages handle exact @page routes better - Search engines know standard sitemap.xml paths - No /api prefix routing conflicts - Direct SSR rendering without endpoint routing Verification for Google/Naver: ✓ /taxbaik/sitemap.xml (exact match with robots.txt) ✓ Content-Type: application/xml ✓ Valid XML structure ✓ Dynamic blog posts included Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,61 +0,0 @@
|
|||||||
using FastEndpoints;
|
|
||||||
using TaxBaik.Application.Services;
|
|
||||||
|
|
||||||
namespace TaxBaik.Web.Endpoints;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// GET /api/sitemap.xml - 동적 사이트맵 생성
|
|
||||||
/// 블로그 포스트, FAQ, 공지사항 포함
|
|
||||||
/// </summary>
|
|
||||||
public class SitemapEndpoint : EndpointWithoutRequest<string>
|
|
||||||
{
|
|
||||||
private readonly BlogService _blogService;
|
|
||||||
|
|
||||||
public SitemapEndpoint(BlogService blogService)
|
|
||||||
{
|
|
||||||
_blogService = blogService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Configure()
|
|
||||||
{
|
|
||||||
Get("/sitemap.xml");
|
|
||||||
AllowAnonymous();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<string> ExecuteAsync(CancellationToken ct)
|
|
||||||
{
|
|
||||||
var baseUrl = "https://www.taxbaik.com/taxbaik";
|
|
||||||
var urls = new List<string>
|
|
||||||
{
|
|
||||||
// 정적 페이지
|
|
||||||
$"{baseUrl}",
|
|
||||||
$"{baseUrl}/about",
|
|
||||||
$"{baseUrl}/services",
|
|
||||||
$"{baseUrl}/contact",
|
|
||||||
$"{baseUrl}/privacy",
|
|
||||||
$"{baseUrl}/terms",
|
|
||||||
$"{baseUrl}/blog",
|
|
||||||
$"{baseUrl}/faq",
|
|
||||||
$"{baseUrl}/announcement",
|
|
||||||
$"{baseUrl}/inquiry"
|
|
||||||
};
|
|
||||||
|
|
||||||
// 동적 블로그 포스트
|
|
||||||
var (posts, _) = await _blogService.GetPublishedPagedAsync(1, 1000, categoryId: null, ct: ct);
|
|
||||||
foreach (var post in posts)
|
|
||||||
{
|
|
||||||
urls.Add($"{baseUrl}/blog/{post.Slug}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// XML 생성
|
|
||||||
var now = DateTime.UtcNow.ToString("yyyy-MM-dd");
|
|
||||||
var urlEntries = string.Join("\n", urls.Select(url =>
|
|
||||||
$" <url>\n <loc>{System.Net.WebUtility.HtmlEncode(url)}</loc>\n <lastmod>{now}</lastmod>\n </url>"));
|
|
||||||
|
|
||||||
var xml = $"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n{urlEntries}\n</urlset>";
|
|
||||||
|
|
||||||
// XML Content-Type 설정
|
|
||||||
HttpContext.Response.ContentType = "application/xml; charset=utf-8";
|
|
||||||
return xml;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
@page "/sitemap.xml"
|
||||||
|
@model TaxBaik.Web.Pages.SitemapModel
|
||||||
|
@{
|
||||||
|
Response.ContentType = "application/xml; charset=utf-8";
|
||||||
|
}<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
@foreach (var url in Model.Urls)
|
||||||
|
{
|
||||||
|
<url>
|
||||||
|
<loc>@System.Net.WebUtility.HtmlEncode(url)</loc>
|
||||||
|
<lastmod>@DateTime.UtcNow:yyyy-MM-dd</lastmod>
|
||||||
|
</url>
|
||||||
|
}
|
||||||
|
</urlset>
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
using TaxBaik.Application.Services;
|
||||||
|
|
||||||
|
namespace TaxBaik.Web.Pages;
|
||||||
|
|
||||||
|
public class SitemapModel : PageModel
|
||||||
|
{
|
||||||
|
private readonly BlogService _blogService;
|
||||||
|
|
||||||
|
public List<string> Urls { get; set; } = [];
|
||||||
|
|
||||||
|
public SitemapModel(BlogService blogService)
|
||||||
|
{
|
||||||
|
_blogService = blogService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task OnGetAsync()
|
||||||
|
{
|
||||||
|
var baseUrl = "https://www.taxbaik.com/taxbaik";
|
||||||
|
|
||||||
|
// 정적 페이지
|
||||||
|
Urls.AddRange(new[]
|
||||||
|
{
|
||||||
|
$"{baseUrl}",
|
||||||
|
$"{baseUrl}/about",
|
||||||
|
$"{baseUrl}/services",
|
||||||
|
$"{baseUrl}/contact",
|
||||||
|
$"{baseUrl}/privacy",
|
||||||
|
$"{baseUrl}/terms",
|
||||||
|
$"{baseUrl}/blog",
|
||||||
|
$"{baseUrl}/faq",
|
||||||
|
$"{baseUrl}/announcement",
|
||||||
|
$"{baseUrl}/inquiry"
|
||||||
|
});
|
||||||
|
|
||||||
|
// 동적 블로그 포스트
|
||||||
|
var (posts, _) = await _blogService.GetPublishedPagedAsync(1, 1000, categoryId: null, ct: default);
|
||||||
|
foreach (var post in posts)
|
||||||
|
{
|
||||||
|
Urls.Add($"{baseUrl}/blog/{post.Slug}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user