Перенаправление на ту же страницу с дополнительным параметром

Я использую локализацию запроса в приложении NET Core 7 и Razor Pages:

      builder.Services.AddRazorPages();

builder.Services.Configure<RequestLocalizationOptions>(options => {
  options.DefaultRequestCulture = new RequestCulture("pt");
  options.SupportedCultures = new List<CultureInfo> { new CultureInfo("en"), new CultureInfo("pt") };
  options.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider { 
    RouteDataStringKey = "culture",
    UIRouteDataStringKey = "culture",
    Options = options
  }); 
});

WebApplication application = builder.Build();

application.UseRouting();
application.MapRazorPages();

application.UseRequestLocalization();

// ...

Вот несколько моих бритвенных страниц:

      Index: @page "/{culture?}"     Example: /pt

About: @page "/{culture?}/about"   Example: /pt/about

Когдаcultureявляетсяnullили неверный. Я хочу перенаправить на ту же страницу с культурой по умолчанию.

Я пытаюсь сделать это с помощью промежуточного программного обеспечения:

      public class RedirectUnsupportedCulturesMiddleware {

    private readonly RequestDelegate _next;
    private readonly string _routeDataStringKey;

    public RedirectUnsupportedCulturesMiddleware(
        RequestDelegate next,
        IOptions<RequestLocalizationOptions> monitor) {

        RequestLocalizationOptions options = monitor.Value;
        _next = next;
        var provider = options.RequestCultureProviders
            .Select(x => x as RouteDataRequestCultureProvider)
            .Where(x => x != null)
            .FirstOrDefault();
        _routeDataStringKey = provider.RouteDataStringKey;
    }

    public async Task Invoke(HttpContext context) {

        var requestedCulture = context.GetRouteValue(_routeDataStringKey)?.ToString();
        var cultureFeature = context.Features.Get<IRequestCultureFeature>();

        var actualCulture = cultureFeature?.RequestCulture.Culture.Name;

        if (string.IsNullOrEmpty(requestedCulture) ||
            !string.Equals(requestedCulture, actualCulture, StringComparison.OrdinalIgnoreCase)) {
            var newCulturedPath = GetNewPath(context, actualCulture);
            context.Response.Redirect(newCulturedPath);
            return;
        }

        await _next.Invoke(context);
    }

    private string GetNewPath(HttpContext context, string newCulture) {

        var routeData = context.GetRouteData();

        var router = routeData.Routers[0];
        var virtualPathContext = new VirtualPathContext(
            context,
            routeData.Values,
            new RouteValueDictionary { { _routeDataStringKey, newCulture } });

        return router.GetVirtualPath(virtualPathContext).VirtualPath;
    }
}

Когда я обращаюсь к домашней странице, например, "/", я получаю исключение в следующем:

      var router = routeData.Routers[0];

Вопросы

  1. Как это решить?
  2. Могу ли я использовать перенаправление 301 из промежуточного программного обеспечения?
  3. Могу ли я использовать Net CoreUseRewriterдля достижения той же цели?

1 ответ

Вот целая рабочая демонстрация, которой вы можете следовать:

1.ПользовательскийIPageRouteModelConventionчтобы отобразить маршрут, а затем не нужно изменять маршрут страницы, например@page "/{culture?}/xxx"

      public class CustomCultureRouteRouteModelConvention : IPageRouteModelConvention
{
    public void Apply(PageRouteModel model)
    {
        List<SelectorModel> selectorModels = new List<SelectorModel>();
        foreach (var selector in model.Selectors.ToList())
        {
            var template = selector.AttributeRouteModel.Template;
            selectorModels.Add(new SelectorModel()
            {
                AttributeRouteModel = new AttributeRouteModel
                {
                    Template = "/{culture}" + "/" + template
                }
            });
        }
        foreach (var m in selectorModels)
        {
            model.Selectors.Add(m);
        }
    }
}

2. Добавьте соглашения об этой странице в Program.cs.

      builder.Services.AddRazorPages().AddRazorPagesOptions(opts =>
{
    opts.Conventions.Add(new CustomCultureRouteRouteModelConvention());  //add this...
});
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
builder.Services.Configure<RequestLocalizationOptions>(
    opt =>
    {
       var supportCulteres = new List<CultureInfo>
       {
           new CultureInfo("pt"),
           new CultureInfo("fr")
       };
       opt.DefaultRequestCulture = new RequestCulture("pt");
       opt.SupportedCultures = supportCulteres;
       opt.SupportedUICultures = supportCulteres;
       opt.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider()); //add this...
   });

3. Порядок промежуточного программного обеспечения

      var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}


//app.UseRequestLocalization();
app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
app.UseRequestLocalization();  //be sure add here......
app.UseAuthorization();

app.MapRazorPages();

app.Run();

Результат:

Другие вопросы по тегам