Files
FrontOffice/src/FrontOffice.Main/Program.cs
T
masoodafar-web 7f5a4f2c37
Build and Deploy to Kubernetes / build-and-deploy (push) Has been cancelled
feat: enhance SEO and sitemap functionality
- Updated the sitemap generation to return a byte array instead of a string for improved performance.
- Added new SEO metadata for categories and store chooser routes to enhance search engine visibility.
- Implemented redirects for legacy wishlist URLs to the homepage, improving user experience.
- Updated robots.txt to disallow indexing of specific paths, ensuring better control over search engine crawling.

These changes significantly improve the SEO capabilities and sitemap handling of the application, enhancing both performance and user navigation.
2026-07-03 06:04:44 +03:30

104 lines
3.2 KiB
C#

using FluentValidation;
using FrontOffice.Main.Utilities;
using FrontOffice.Main.Utilities.Seo;
using System.Net;
using FrontOffice.Main.Utilities.Pdf;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
#region AddCommonServices
builder.Services.AddCommonServices();
builder.Services.Configure<SeoSettings>(builder.Configuration.GetSection(SeoSettings.SectionName));
builder.Services.AddSingleton<MainService>();
#endregion
#region AddGrpcServices
builder.Services.AddGrpcServices(builder.Configuration);
#endregion
#region FluentValidation
ValidatorOptions.Global.LanguageManager = new CustomFluentValidationLanguageManager();
#endregion
var appSettings = builder.Configuration.Get<AppSettings>();
if (!string.IsNullOrWhiteSpace(appSettings?.DownloadUrl))
{
UrlUtility.DownloadUrl = appSettings.DownloadUrl;
}
else
{
UrlUtility.DownloadUrl = string.Empty; // fallback to empty
}
builder.Services.Configure<EncryptionSettings>(builder.Configuration.GetSection("EncryptionSettings"));
builder.Services.AddSingleton<MobileNumberEncryptor>();
var webApp = builder.Build();
// Configure the HTTP request pipeline.
if (!webApp.Environment.IsDevelopment())
{
webApp.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
webApp.UseHsts();
}
webApp.UseHttpsRedirection();
webApp.UseStaticFiles();
webApp.UseRouting();
webApp.MapBlazorHub();
webApp.MapGet("/sitemap.xml", async (SitemapGenerator sitemapGenerator, CancellationToken cancellationToken) =>
{
var bytes = await sitemapGenerator.GenerateBytesAsync(cancellationToken);
return Results.File(bytes, "application/xml; charset=utf-8");
});
// Legacy URLs from old site / common e-commerce paths — redirect to homepage
webApp.MapGet("/wishlist", () => Results.Redirect("/", permanent: true));
webApp.MapGet("/wishlist/", () => Results.Redirect("/", permanent: true));
webApp.MapFallbackToPage("/_Host");
webApp.MapGet("/contract/generate",async (string html, string? fileName, IChromiumPdfService pdfService) =>
{
var decoded = WebUtility.UrlDecode(html);
var safeName = string.IsNullOrWhiteSpace(fileName) ? "contract" : fileName.Trim();
var bytes =await pdfService.GeneratePdfAsync(decoded, safeName);
return Results.File(bytes, "application/pdf", safeName + ".pdf");
});
// Support large HTML via POST (body) to avoid URL length limits
webApp.MapPost("/contract/generate", async (ContractPdfRequest req, IChromiumPdfService pdfService) =>
{
if (string.IsNullOrWhiteSpace(req.Html)) return Results.BadRequest("Empty html");
var safeName = string.IsNullOrWhiteSpace(req.FileName) ? "contract" : req.FileName.Trim();
var bytes = await pdfService.GeneratePdfAsync(req.Html, safeName);
return Results.File(bytes, "application/pdf", safeName + ".pdf");
});
webApp.Run();
public sealed record ContractPdfRequest(string Html, string? FileName);
public class AppSettings
{
public required string DownloadUrl { get; set; }
}
public class EncryptionSettings
{
public required string Key { get; set; }
public required string IV { get; set; }
}