.net 不迁移“区域性”查询字符串

jm2pwxwz  于 2023-10-21  发布在  .NET
关注(0)|答案(2)|浏览(104)
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

emeijp43

emeijp431#

在ASP.NET Core 6 MVC中,本地化被深度集成到路由系统中。RequestLocalizationMiddleware自动从请求中检测所需的区域性,并为该请求设置当前区域性。这样,您就可以拥有本地化的路由,而无需在路由模板中显式指定区域性。
因此,在ASP.NETCore6MVC项目中,不需要在路由链接中显式包含asp-route-culture="..."。框架自动从请求中检测区域性并将其应用于路由。
这是一个设计改进,使本地化更加无缝,并集成到框架中。它简化了开发人员的流程,并为用户提供了更一致的体验。
在您的ASP.NET Core 6 MVC项目中,以下路由配置正在处理本地化:

app.MapControllerRoute(
    name: "LocalizedDefault",
    pattern: "{culture:culture}/{controller=Home}/{action=Index}/{id?}"
);
ffscu2ro

ffscu2ro2#

根据文献资料和讨论,本文设计了一种新型的多媒体播放器.在用户真实的情况下,这是一种防止路线混淆的设计,如有面积的项目,虽然会带来一些不便。
到目前为止,你可以通过覆盖锚标记助手和url生成器或像你一样添加asp-route-value来让它正确工作。这是文件。https://github.com/dotnet/aspnetcore/issues/16960

相关问题