public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddLocalization();
services.AddMvc(option => option.EnableEndpointRouting = false);
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("tr-TR")
};
options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
options.RequestCultureProviders = new[] { new RouteDataRequestCultureProvider {
IndexOfCulture = 1,
IndexofUICulture = 1
}};
});
services.Configure<RouteOptions>(options =>
{
options.ConstraintMap.Add("culture", typeof(LanguageRouteConstraint));
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
var locOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(locOptions.Value);
app.UseHttpsRedirection();
//SEO - jpg, css, js gibi dosyalara cache eklemek için
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
const int durationInSeconds = 60 * 60 * 24 * 365;
ctx.Context.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.CacheControl]
= "public,max-age=" + durationInSeconds;
}
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "LocalizedDefault",
template: "{culture:culture}/{controller=Home}/{action=Index}/{id?}"
);
routes.MapRoute(
name: "DefaultNonLocalized",
template: "{controller}/{action}/{id?}"
);
routes.MapRoute(
name: "default",
template: "",
defaults: new { controller = "Home", action = "RedirectToDefaultLanguage", culture = "tr" });
routes.MapRoute(
name: "error",
template: "{*catchall}",
defaults: new { controller = "Error", action = "HandleError", statusCode = 404 });
});
}
public class LanguageRouteConstraint : IRouteConstraint
{
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
if (!values.ContainsKey("culture"))
return false;
var culture = values["culture"].ToString();
return culture == "en" || culture == "tr";
}
}
public class RouteDataRequestCultureProvider : RequestCultureProvider
{
public int IndexOfCulture;
public int IndexofUICulture;
public override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
{
if (httpContext == null)
throw new ArgumentNullException(nameof(httpContext));
string culture = null;
string uiCulture = null;
var twoLetterCultureName = httpContext.Request.Path.Value.Split('/')[IndexOfCulture]?.ToString();
var twoLetterUICultureName = httpContext.Request.Path.Value.Split('/')[IndexofUICulture]?.ToString();
if (twoLetterCultureName == "tr")
culture = "tr-TR";
else if (twoLetterCultureName == "en")
culture = "en-US";
if (twoLetterUICultureName == "tr")
uiCulture = "tr-TR";
else if (twoLetterUICultureName == "en")
uiCulture = "en-US";
if (culture == null && uiCulture == null)
return NullProviderCultureResult;
if (culture != null && uiCulture == null)
uiCulture = culture;
if (culture == null && uiCulture != null)
culture = uiCulture;
var providerResultCulture = new ProviderCultureResult(culture, uiCulture);
return Task.FromResult(providerResultCulture);
}
}
public ActionResult RedirectToDefaultLanguage()
{
return RedirectToAction("Index", new { culture = "en"});
}
[Route("{culture}")]
public IActionResult Index(string culture)
{
MainViewModel model = new MainViewModel();
ProductListViewModel m1 = new ProductListViewModel();
ProductListViewModel m2 = new ProductListViewModel();
if (culture == "tr")
{
m1.Id = 1;
m1.Name = "ürün 1 tr";
m1.SeoUrl = "urun-tr";
m2.Id = 2;
m2.Name = "ürün 2 tr";
m2.SeoUrl = "urun-tr";
}
else
{
m1.Id = 1;
m1.Name = "product 1 en";
m1.SeoUrl = "product-en";
m2.Id = 2;
m2.Name = "product 2 en";
m2.SeoUrl = "product-en";
}
model.Products.Add(m1);
model.Products.Add(m2);
return View(model);
}
[Route("{culture}/{seoTag:regex(egitim|training)}/{productUrl}-{productId:int}-{seoTag2:regex([[egitimi$|training$]])}/", Name = "productLink")]
public ActionResult ProductDetails(string culture, int productId, string productUrl)
{
return View();
}
//IN VIEW
//Everything works
@foreach (var item in Model.Products)
{
<div>
<a asp-route="productLink" asp-route-productId="@item.Id" asp-route-productUrl="@item.SeoUrl" asp-route-seoTag="@SharedLocalizer["TrainingSeoTag"]" asp-route-seoTag2="@SharedLocalizer["ProductSeoUrl"]">
@item.Name
</a>
</div>
<hr />
}
没有asp-route-culture="*culture-code*"
,但链接到其他页面时仍然携带“文化”。
当您使用ASP.NETCore6MVC执行此项目时,“区域性”查询字符串不会移动到其他页面。我需要添加asp-route-culture="*code"
参数。
这是ASP.NET Core 6 MVC代码:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews(option => option.EnableEndpointRouting = false);
builder.Services.AddHttpContextAccessor();
builder.Services.AddLocalization();
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("tr-TR"),
new CultureInfo("es-US")
};
options.DefaultRequestCulture = new RequestCulture(culture: "tr-TR", uiCulture: "tr-TR");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
options.RequestCultureProviders = new[] { new Custom2RequestCultureProvider {
IndexOfCulture = 1,
IndexofUICulture = 1
}
};
});
builder.Services.Configure<RouteOptions>(options =>
{
options.ConstraintMap.Add("culture", typeof(LanguageRouteConstraint));
});
var app = builder.Build();
var options = app.Services.GetRequiredService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(options.Value);
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.MapControllerRoute(
name: "LocalizedDefault",
pattern: "{culture:culture}/{controller=Home}/{action=Index}/{id?}"
);
app.MapControllerRoute(
name: "DefaultNonLocalized",
pattern: "{controller}/{action}/{id?}"
);
app.MapControllerRoute(
name: "default",
pattern: "",
defaults: new { controller = "Home", action = "RedirectToDefaultLanguage", culture = "tr-TR" });
app.MapControllerRoute(
name: "error",
pattern: "{*catchall}",
defaults: new { controller = "Error", action = "HandleError", statusCode = 404 });
app.Run();
//***
//IN VIEW
//If I don't add asp-route-culture="en" it doesn't work
//***
<a asp-route="productLink" asp-route-productId="@item.Id" asp-route-productUrl="@item.SeoUrl" asp-route-seoTag="@SharedLocalizer["TrainingSeoTag"]" asp-route-seoTag2="@SharedLocalizer["ProductSeoUrl"]">
@item.Name
</a>
问题:为什么asp-route-culture=""
在ASP.NET MVC 3中不需要,但在ASP.NET Core 6 MVC中需要?
我的ASP.NET MVC 3项目文件:https://filetransfer.io/data-package/ljsHJom3#link
我的ASP.NET Core 6 MVC项目文件:https://filetransfer.io/data-package/Go4VK5FB#link
2条答案
按热度按时间emeijp431#
在ASP.NET Core 6 MVC中,本地化被深度集成到路由系统中。
RequestLocalizationMiddleware
自动从请求中检测所需的区域性,并为该请求设置当前区域性。这样,您就可以拥有本地化的路由,而无需在路由模板中显式指定区域性。因此,在ASP.NETCore6MVC项目中,不需要在路由链接中显式包含
asp-route-culture="..."
。框架自动从请求中检测区域性并将其应用于路由。这是一个设计改进,使本地化更加无缝,并集成到框架中。它简化了开发人员的流程,并为用户提供了更一致的体验。
在您的ASP.NET Core 6 MVC项目中,以下路由配置正在处理本地化:
ffscu2ro2#
根据文献资料和讨论,本文设计了一种新型的多媒体播放器.在用户真实的情况下,这是一种防止路线混淆的设计,如有面积的项目,虽然会带来一些不便。
到目前为止,你可以通过覆盖锚标记助手和url生成器或像你一样添加asp-route-value来让它正确工作。这是文件。https://github.com/dotnet/aspnetcore/issues/16960