فرض کنید اکشن متدی را به صورت زیر تعریف کردهاید:
namespace MvcHealthCheckTest.Controllers
{
public class HomeController : Controller
{
public IActionResult ViewDetails()
{
return View();
}
زمانیکه لینکی را برای آن تعریف میکنید:
<a asp-controller="Home" asp-action="ViewDetails">View Details</a>
در حین رندر نهایی آن، چنین شکلی را پیدا میکند (قسمت ViewDetails آن دقیقا با نام اکشن متد متناظر و بزرگی و کوچکی حروف آن تطابق دارد):
https://localhost:5001/Home/ViewDetails
اکنون قصد داریم، یک چنین URLهایی را در کل برنامه به صورت زیر رندر کنیم:
الف) تمام مسیرها lowercase باشند (مناسب برای SEO؛ از این جهت که تعداد مسیرهای تکراری یکسان با حروف بزرگ و کوچک، به حداقل میرسند)
ب) ViewDetailsها تبدیل به view-details شوند. یعنی بین حروف جدا شدهی با کلمات بزرگ و کوچک، یک - قرار گیرد.
انجام یک چنین تغییرات سراسری در ASP.NET Core 2.2 با معرفی IOutboundParameterTransformer میسر شدهاست:
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Routing;
public class CustomUrlTransformer : IOutboundParameterTransformer
{
public string TransformOutbound(object value)
{
return value == null ? null : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2");
}
}
در اینجا یک تغییرشکل دهندهی سراسری URLها را با پیاده سازی اینترفیس IOutboundParameterTransformer تدارک دیدهایم که توسط آن بین حروف بزرگ و کوچک، یک - قرار میدهد.
روش معرفی آن نیز به سیستم به صورت زیر است:
ابتدا نیاز است این Transformer به صورت یک ConstraintMap جدید به سیستم مسیریابی اضافه شود. در اینجا امکان تنظیم تولید LowercaseUrls نیز وجود دارد. به همین جهت نیازی نیست تا در متد TransformOutbound فوق، در انتهای کار، متد ToLower را نیز فراخوانی کنیم:
namespace MvcTest
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddRouting(option =>
{
option.ConstraintMap.Add(key: "transformer1", value: typeof(CustomUrlTransformer));
option.LowercaseUrls = true;
});
}
سپس باید قالب مسیریابی را نیز به صورت زیر تغییر دهیم و کلید ConstraintMap اضافه شدهی فوق را به اجزای آن اضافه کنیم:
namespace MvcTest
{
public class Startup
{
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ...
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller:transformer1}/{action:transformer1}/{id?}",
defaults: new { controller = "Home", action = "Index" }
);
});
}
که template و defaults آن را به صورت خلاصهی زیر نیز میتوان نوشت:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller:transformer1=Home}/{action:transformer1=Index}/{id?}"
);
});
اکنون اگر برنامه را اجرا کنیم، اینبار URL تولیدی، بجای https://localhost:5001/Home/ViewDetails به صورت زیر رندر میشود:
https://localhost:5001/home/view-details