fix: google search
This commit is contained in:
parent
707dab8075
commit
ea6eacc6c6
@ -205,134 +205,91 @@ namespace QRRapidoApp.Controllers
|
||||
return Ok(new { status = "healthy", timestamp = DateTime.UtcNow });
|
||||
}
|
||||
|
||||
// Sitemap endpoint for SEO
|
||||
[Route("sitemap.xml")]
|
||||
public async Task<IActionResult> Sitemap()
|
||||
{
|
||||
var baseUrl = "https://qrrapido.site";
|
||||
var now = DateTime.UtcNow.ToString("yyyy-MM-dd");
|
||||
|
||||
var sitemapBuilder = new System.Text.StringBuilder();
|
||||
sitemapBuilder.AppendLine(@"<?xml version=""1.0"" encoding=""UTF-8""?>");
|
||||
sitemapBuilder.AppendLine(@"<urlset xmlns=""http://www.sitemaps.org/schemas/sitemap/0.9"">");
|
||||
|
||||
// Static pages
|
||||
sitemapBuilder.AppendLine($@"
|
||||
<url>
|
||||
<loc>{baseUrl}/</loc>
|
||||
<lastmod>{now}</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>{baseUrl}/pt/</loc>
|
||||
<lastmod>{now}</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
<priority>0.9</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>{baseUrl}/es/</loc>
|
||||
<lastmod>{now}</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
<priority>0.9</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>{baseUrl}/pt-BR/About</loc>
|
||||
<lastmod>{now}</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>{baseUrl}/es-PY/About</loc>
|
||||
<lastmod>{now}</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>{baseUrl}/pt-BR/Contact</loc>
|
||||
<lastmod>{now}</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>{baseUrl}/es-PY/Contact</loc>
|
||||
<lastmod>{now}</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>{baseUrl}/pt-BR/FAQ</loc>
|
||||
<lastmod>{now}</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.9</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>{baseUrl}/es-PY/FAQ</loc>
|
||||
<lastmod>{now}</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.9</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>{baseUrl}/pt-BR/HowToUse</loc>
|
||||
<lastmod>{now}</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>{baseUrl}/es-PY/HowToUse</loc>
|
||||
<lastmod>{now}</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>{baseUrl}/Pagamento/SelecaoPlano</loc>
|
||||
<lastmod>{now}</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>{baseUrl}/privacy</loc>
|
||||
<lastmod>{now}</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.5</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>{baseUrl}/terms</loc>
|
||||
<lastmod>{now}</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.5</priority>
|
||||
</url>");
|
||||
|
||||
// Dynamic tutorial pages
|
||||
try
|
||||
{
|
||||
var allArticles = await _markdownService.GetAllArticlesForSitemapAsync();
|
||||
|
||||
foreach (var article in allArticles)
|
||||
{
|
||||
var slug = article.Title.ToLower().Replace(" ", "-");
|
||||
var lastMod = article.LastMod.ToString("yyyy-MM-dd");
|
||||
|
||||
sitemapBuilder.AppendLine($@"
|
||||
<url>
|
||||
<loc>{baseUrl}/{article.Culture}/tutoriais/{slug}</loc>
|
||||
<lastmod>{lastMod}</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>");
|
||||
}
|
||||
|
||||
_logger.LogInformation("Generated sitemap with {Count} tutorial articles", allArticles.Count);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error adding tutorials to sitemap");
|
||||
}
|
||||
|
||||
sitemapBuilder.AppendLine("</urlset>");
|
||||
|
||||
return Content(sitemapBuilder.ToString(), "application/xml");
|
||||
}
|
||||
// Sitemap endpoint for SEO
|
||||
[Route("sitemap.xml")]
|
||||
public async Task<IActionResult> Sitemap()
|
||||
{
|
||||
var baseUrl = "https://qrrapido.site";
|
||||
var now = DateTime.UtcNow.ToString("yyyy-MM-dd");
|
||||
|
||||
var sitemapBuilder = new System.Text.StringBuilder();
|
||||
sitemapBuilder.AppendLine(@"<?xml version=""1.0"" encoding=""UTF-8""?>");
|
||||
sitemapBuilder.AppendLine(@"<urlset xmlns=""http://www.sitemaps.org/schemas/sitemap/0.9"">");
|
||||
|
||||
void AppendUrl(string relativePath, string changeFreq, string priority, string? lastModOverride = null)
|
||||
{
|
||||
var normalizedPath = relativePath.StartsWith("/")
|
||||
? relativePath
|
||||
: $"/{relativePath}";
|
||||
|
||||
var lastModValue = lastModOverride ?? now;
|
||||
|
||||
sitemapBuilder.AppendLine($@"
|
||||
<url>
|
||||
<loc>{baseUrl}{normalizedPath}</loc>
|
||||
<lastmod>{lastModValue}</lastmod>
|
||||
<changefreq>{changeFreq}</changefreq>
|
||||
<priority>{priority}</priority>
|
||||
</url>");
|
||||
}
|
||||
|
||||
// Core entry points
|
||||
AppendUrl("/", "daily", "1.0");
|
||||
AppendUrl("/pt-BR", "daily", "0.9");
|
||||
AppendUrl("/es-PY", "daily", "0.9");
|
||||
|
||||
var cultures = new[] { "pt-BR", "es-PY" };
|
||||
var informationalPages = new[]
|
||||
{
|
||||
new { Path = "Home/About", ChangeFreq = "monthly", Priority = "0.8" },
|
||||
new { Path = "Home/Contact", ChangeFreq = "monthly", Priority = "0.8" },
|
||||
new { Path = "Home/FAQ", ChangeFreq = "weekly", Priority = "0.9" },
|
||||
new { Path = "Home/HowToUse", ChangeFreq = "weekly", Priority = "0.8" },
|
||||
new { Path = "Home/Privacy", ChangeFreq = "monthly", Priority = "0.5" },
|
||||
new { Path = "Home/Terms", ChangeFreq = "monthly", Priority = "0.5" }
|
||||
};
|
||||
|
||||
foreach (var page in informationalPages)
|
||||
{
|
||||
AppendUrl($"/{page.Path}", page.ChangeFreq, page.Priority);
|
||||
}
|
||||
|
||||
foreach (var culture in cultures)
|
||||
{
|
||||
foreach (var page in informationalPages)
|
||||
{
|
||||
AppendUrl($"/{culture}/{page.Path}", page.ChangeFreq, page.Priority);
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamic tutorial pages
|
||||
try
|
||||
{
|
||||
var allArticles = await _markdownService.GetAllArticlesForSitemapAsync();
|
||||
|
||||
foreach (var article in allArticles)
|
||||
{
|
||||
var slug = !string.IsNullOrWhiteSpace(article.Slug)
|
||||
? article.Slug
|
||||
: article.Title.ToLower().Replace(" ", "-");
|
||||
|
||||
var encodedSlug = System.Uri.EscapeDataString(slug);
|
||||
var lastMod = article.LastMod.ToString("yyyy-MM-dd");
|
||||
|
||||
AppendUrl($"/{article.Culture}/tutoriais/{encodedSlug}", "weekly", "0.8", lastMod);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Generated sitemap with {Count} tutorial articles", allArticles.Count);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error adding tutorials to sitemap");
|
||||
}
|
||||
|
||||
sitemapBuilder.AppendLine("</urlset>");
|
||||
|
||||
return Content(sitemapBuilder.ToString(), "application/xml");
|
||||
}
|
||||
}
|
||||
|
||||
//public class ErrorViewModel
|
||||
@ -340,4 +297,4 @@ namespace QRRapidoApp.Controllers
|
||||
// public string? RequestId { get; set; }
|
||||
// public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace QRRapidoApp.Middleware
|
||||
{
|
||||
@ -7,6 +8,12 @@ namespace QRRapidoApp.Middleware
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly ILogger<LanguageRedirectionMiddleware> _logger;
|
||||
private readonly string[] _supportedCultures = { "pt-BR", "es-PY" };
|
||||
private readonly Dictionary<string, string> _cultureAliases = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ "pt", "pt-BR" },
|
||||
{ "pt-br", "pt-BR" },
|
||||
{ "es", "es-PY" }
|
||||
};
|
||||
private const string DefaultCulture = "pt-BR";
|
||||
|
||||
public LanguageRedirectionMiddleware(RequestDelegate next, ILogger<LanguageRedirectionMiddleware> logger)
|
||||
@ -19,6 +26,11 @@ namespace QRRapidoApp.Middleware
|
||||
{
|
||||
var path = context.Request.Path.Value?.TrimStart('/') ?? "";
|
||||
|
||||
if (TryHandleCultureAlias(context, path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasCultureInPath(path) || IsSpecialRoute(path))
|
||||
{
|
||||
await _next(context);
|
||||
@ -63,6 +75,40 @@ namespace QRRapidoApp.Middleware
|
||||
return _supportedCultures.Contains(segments[0]);
|
||||
}
|
||||
|
||||
private bool TryHandleCultureAlias(HttpContext context, string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var segments = path.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
||||
if (segments.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var firstSegment = segments[0];
|
||||
if (_cultureAliases.TryGetValue(firstSegment, out var mappedCulture))
|
||||
{
|
||||
var remainingSegments = segments.Length > 1
|
||||
? "/" + string.Join('/', segments.Skip(1))
|
||||
: string.Empty;
|
||||
|
||||
var redirectUrl = $"/{mappedCulture}{remainingSegments}";
|
||||
if (context.Request.QueryString.HasValue)
|
||||
{
|
||||
redirectUrl += context.Request.QueryString.Value;
|
||||
}
|
||||
|
||||
_logger.LogInformation("Redirecting alias '{Alias}' to canonical culture URL: {RedirectUrl}", firstSegment, redirectUrl);
|
||||
context.Response.Redirect(redirectUrl, permanent: true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsSpecialRoute(string path)
|
||||
{
|
||||
var specialRoutes = new[]
|
||||
@ -110,4 +156,4 @@ namespace QRRapidoApp.Middleware
|
||||
return DefaultCulture;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
@{
|
||||
var isDevelopment = HostEnvironment?.IsDevelopment() ?? false;
|
||||
var isPremiumUser = false;
|
||||
var currentCulture = System.Globalization.CultureInfo.CurrentUICulture?.Name ?? "pt-BR";
|
||||
|
||||
if (User?.Identity?.IsAuthenticated == true)
|
||||
{
|
||||
@ -26,7 +27,7 @@
|
||||
}
|
||||
}
|
||||
<!DOCTYPE html>
|
||||
<html lang="pt-BR">
|
||||
<html lang="@currentCulture">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
@ -47,9 +48,8 @@
|
||||
<link rel="canonical" href="@Context.Request.GetDisplayUrl()">
|
||||
|
||||
<!-- Hreflang for multilingual -->
|
||||
<link rel="alternate" hreflang="pt-BR" href="https://qrrapido.site/pt/">
|
||||
<link rel="alternate" hreflang="es" href="https://qrrapido.site/es/">
|
||||
<link rel="alternate" hreflang="en" href="https://qrrapido.site/en/">
|
||||
<link rel="alternate" hreflang="pt-BR" href="https://qrrapido.site/pt-BR/">
|
||||
<link rel="alternate" hreflang="es-PY" href="https://qrrapido.site/es-PY/">
|
||||
<link rel="alternate" hreflang="x-default" href="https://qrrapido.site/">
|
||||
|
||||
<!-- Open Graph -->
|
||||
|
||||
@ -176,7 +176,7 @@
|
||||
<div class="list-group list-group-flush">
|
||||
@foreach (var related in Model.RelatedArticles)
|
||||
{
|
||||
<a href="/@ViewBag.Culture/tutoriais/@related.Title.ToLower().Replace(" ", "-")"
|
||||
<a href="/@ViewBag.Culture/tutoriais/@related.Slug"
|
||||
class="list-group-item list-group-item-action">
|
||||
<h6 class="mb-1">@related.Title</h6>
|
||||
<p class="mb-1 text-muted small">@related.Description</p>
|
||||
|
||||
@ -2,8 +2,6 @@ User-agent: *
|
||||
Allow: /
|
||||
|
||||
Sitemap: https://qrrapido.site/sitemap.xml
|
||||
Sitemap: https://qrrapido.site/pt-BR/sitemap.xml
|
||||
Sitemap: https://qrrapido.site/es-PY/sitemap.xml
|
||||
|
||||
Disallow: /Admin/
|
||||
Disallow: /Identity/
|
||||
|
||||
Loading…
Reference in New Issue
Block a user