Asp.net .Net Core 3.1 Razor页面:自动更正到区域性

Asp.net .Net Core 3.1 Razor页面:自动更正到区域性,asp.net,asp.net-core,razor,.net-core,Asp.net,Asp.net Core,Razor,.net Core,我试图用MS Docs实现类似的行为 例如,如果您访问https://docs.microsoft.com/,您将被重定向到您的文化,在我的情况下,我将被自动重定向到https://docs.microsoft.com/en gb/ 如果您访问内部页面时没有URL中的区域性,则内部页面也是如此 例如,通过访问: https://docs.microsoft.com/aspnet/core/razor-pages/?view=aspnetcore-3.1和选项卡=visual studio 它将自

我试图用MS Docs实现类似的行为

例如,如果您访问https://docs.microsoft.com/,您将被重定向到您的文化,在我的情况下,我将被自动重定向到https://docs.microsoft.com/en gb/

如果您访问内部页面时没有URL中的区域性,则内部页面也是如此

例如,通过访问:

https://docs.microsoft.com/aspnet/core/razor-pages/?view=aspnetcore-3.1和选项卡=visual studio

它将自动将您重定向到:

https://docs.microsoft.com/en gb/aspnet/core/razor pages/?view=aspnetcore-3.1&tabs=visual studio

我有一个小的演示应用程序,在那里我对.NETCore3.1和Razor页面进行本地化实验

我已经设置了
选项.约定
,并且创建了
CustomCultureRouteModelConvention
类,但是我对.NET Core非常熟悉,我有点执着于如何实现上述功能

提前谢谢大家

如ms文档中所述;每个本地化请求初始化一个
RequestCultureProvider
列表,并按以下顺序枚举

  • :例如
    http://localhost:1234/Index?culture=en
  • :查找区域性cookie,如果未手动设置,则该区域性cookie将为空
  • :这取决于浏览器文化,这是您需要查找的内容

  • 要确保其工作方式,请删除区域性cookie并通过将所需语言移到顶部来更改浏览器语言首选项,您将看到该语言是根据浏览器首选项选择的。

    您应该使用现有的重写中间件执行重定向: 在最简单的形式中,如果重写中间件在URL路径的开头没有看到区域设置模式,您可以告诉它重定向

    new RewriteOptions().AddRedirect(“^([a-z]{2}-[a-z]{2})”,“en-US/$1”)

    (未测试regex)或使用更详细的规则执行完整的重定向类,并将其重定向到您想要重定向的语言环境。该aspnet文档引用中的示例,可用于了解自定义重定向规则的工作原理。为了适应您的案例作为概念证明,我重用了您现有的
    重定向UnsupportedCulture
    中的大部分逻辑:

    public class RedirectUnsupportedCultures : IRule
        {
            private readonly string _extension;
            private readonly PathString _newPath;
            private IList<CultureInfo> _cultureItems;
            private string _cultureRouteKey;
    
            public RedirectUnsupportedCultures(IOptions<RequestLocalizationOptions> options)
            {
                RouteDataRequestCultureProvider provider = options.Value.RequestCultureProviders
                    .OfType<RouteDataRequestCultureProvider>()
                    .First();
    
                _cultureItems = options.Value.SupportedUICultures;
    
                _cultureRouteKey = provider.RouteDataStringKey;
            }
    
            public void ApplyRule(RewriteContext rewriteContext)
            {
                // do not redirect static assets and do not redirect from a controller that is meant to set the locale
                // similar to how you would not restrict a guest user from login form on public site.
                if (rewriteContext.HttpContext.Request.Path.Value.EndsWith(".ico") ||
                    rewriteContext.HttpContext.Request.Path.Value.Contains("change-culture"))
                {
                    return;
                }
    
                IRequestCultureFeature cultureFeature = rewriteContext.HttpContext.Features.Get<IRequestCultureFeature>();
                string actualCulture = cultureFeature?.RequestCulture.Culture.Name;
                string requestedCulture = rewriteContext.HttpContext.GetRouteValue(_cultureRouteKey)?.ToString();
    
                // Here you can add more rules to redirect based on maybe cookie setting, or even language options saved in database user profile
                if(string.IsNullOrEmpty(requestedCulture) || _cultureItems.All(x => x.Name != requestedCulture)
                    && !string.Equals(requestedCulture, actualCulture, StringComparison.OrdinalIgnoreCase))
                {
                    string localizedPath = $"/{actualCulture}{rewriteContext.HttpContext.Request.Path.Value}";
    
                    HttpResponse response = rewriteContext.HttpContext.Response;
                    response.StatusCode = StatusCodes.Status301MovedPermanently;
                    rewriteContext.Result = RuleResult.EndResponse;
    
                    // preserve query part parameters of the URL (?parameters) if there were any
                    response.Headers[HeaderNames.Location] =
                        localizedPath + rewriteContext.HttpContext.Request.QueryString;
                }
            }
    
    改进: 在使用上述代码后,我遇到了一个bug,如果应用程序不支持区域性,重定向将以无限的区域性路径结束。例如,如果我支持区域性
    en
    (默认)和
    gr
    ,如果不是
    /en/foobar
    /gr/foobar
    ,我将编写
    /fr/foobar
    ,我将得到
    /en/fr/foobar
    ,然后是
    /en/en/fr/foobar
    等等

    我添加了
    private readonly LinkGenerator\u LinkGenerator到类,我在构造函数中初始化它。我删除了那行
    stringlocalizedpath=$“/{actualCulture}{rewriteContext.HttpContext.Request.Path.Value}”该行后面的代码如下所示:

    rewriteContext.HttpContext.GetRouteData().Values[\u cultureRouteKey]=actualCulture;
    HttpResponse response=rewriteContext.HttpContext.response;
    response.StatusCode=StatusCodes.Status301永久移动;
    rewriteContext.Result=RuleResult.EndResponse;
    //保留URL的查询部分参数(?参数)(如果有)
    响应.标题[标题.位置]=
    _linkGenerator.GetPathByAction(
    重写context.HttpContext,
    值:rewriteContext.HttpContext.GetRouteData().values
    )
    +rewriteContext.HttpContext.Request.QueryString;
    
    感谢您的回复,我的问题不是检测区域设置,而是如何正确重定向用户,正如我在文章中所描述的。例如,如果你检查我的演示应用程序,我有两种文化,一种是en-US,另一种是en-GB。访问时,在en US语言环境中,您将看到“欢迎朋友!”消息,在en GB中,您将看到“欢迎小伙子!”。我尝试的是在访问时自动重定向到/{locale}。另外,如果您访问/即将自动重定向到/{locale}/about等。。。我有点挣扎,因为我对.net World相当陌生。我已经检查了你的应用程序,它正在按预期工作。只是不设置区域性cookie,默认情况下它将使用浏览器本地。是的,通过删除cookie,它会检测到浏览器区域设置,我知道,但它不会自动重定向,它会在您的端进行吗?例如,当您访问时,它会自动将您重定向到?非常感谢@alex tech的回复!这确实是我想要的:)@alex tech。。。谢谢你的方法。不过只有一个问题。。如果我们最初的请求是一篇博文,是否有可能在我们的重写位置保留。。。假设我有一个URL/search,它正在将其转换为/en/search,但是如果/search是一个POST请求,那么/en/search在随后的点击中会变成一个GET…@StackAddict看看这里:
    // Attempt to make auto-redirect to culture if it is not exist in the url
    RewriteOptions rewriter = new RewriteOptions();
    rewriter.Add(new RedirectUnsupportedCultures(app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>()));
    app.UseRewriter(rewriter);