c# - MVC 5 如何使用本地化路由定义 Owin LoginPath

标签 c# asp.net-mvc-5 owin

我有一个 MVC 5 网站,其本地化路由定义为

routes.MapRoute(
            name: "Default",
            url: "{culture}/{controller}/{action}/{id}",
            defaults: new { culture = CultureHelper.GetDefaultCulture(), controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

默认区域性导致 "en-US"


问题出现在启动时,我必须使用 LoginPath 属性定义登录 url,该属性设置一次,它将始终使用提供的值,例如如果“/en-Us/Account/Login”是指定值,则为默认文化。然后我尝试使用 UrlHelper 类,希望能体验一些神奇,但结果显然是一样的:

var httpContext = HttpContext.Current;
        if (httpContext == null) {
          var request = new HttpRequest("/", "http://example.com", "");
          var response = new HttpResponse(new StringWriter());
          httpContext = new HttpContext(request, response);
        }

        var httpContextBase = new HttpContextWrapper(httpContext);
        var routeData = new RouteData();
        var requestContext = new RequestContext(httpContextBase, routeData);
        UrlHelper helper = new UrlHelper(requestContext);

        var loginPath = helper.Action("Login", "Account");

        // Enable the application to use a cookie to store information for the signed in user
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,                
            LoginPath = new PathString(loginPath)
        });

我的问题是:有没有办法破解这种动态检索当前文化的机制,或者我是否被迫将当前文化设置到 cookie 中,当我被重定向到登录页面时,使用 cookie 值来在呈现页面之前设置当前文化?

谢谢

最佳答案

我遇到了同样的问题,想出了一个方法来克服这个限制。

CookieAuthenticationOptions 选项中,有一个使用 CookieAuthenticationProvider 初始化的“Provider”属性。这实现了一个名为 ApplyRedirect 的方法和一个委托(delegate) OnApplyRedirect。 我的第一个想法是覆盖此 ApplyRedirect 并实现处理本地化路由所需的逻辑。但不幸的是,它不能被覆盖。将我的逻辑传递给 OnApplyRedirect 会导致覆盖默认行为。理论上你可以捕获 source of this behavior ,将其复制到您的项目中并根据您的需要进行修改,但这显然不是一个好的做法。 首先,我决定围绕 CookieAuthenticationProvider 制作一个包装器,使用委托(delegate)并保留默认行为(使用的 url 除外)的两个扩展点 - 或者更简单地解决包装器(thx to lafi)。

然后在身份验证配置中,我将自定义逻辑添加到提供程序:

public void ConfigureAuth(IAppBuilder app)
{
    UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext);

    CookieAuthenticationProvider provider = new CookieAuthenticationProvider();

    var originalHandler = provider.OnApplyRedirect;

    //Our logic to dynamically modify the path (maybe needs some fine tuning)
    provider.OnApplyRedirect = context =>
    {
        var mvcContext = new HttpContextWrapper(HttpContext.Current);
        var routeData = RouteTable.Routes.GetRouteData(mvcContext);

        //Get the current language  
        RouteValueDictionary routeValues = new RouteValueDictionary();
        routeValues.Add("lang", routeData.Values["lang"]);

        //Reuse the RetrunUrl
        Uri uri = new Uri(context.RedirectUri);
        string returnUrl = HttpUtility.ParseQueryString(uri.Query)[context.Options.ReturnUrlParameter];
        routeValues.Add(context.Options.ReturnUrlParameter, returnUrl);

        //Overwrite the redirection uri
        context.RedirectUri = url.Action("login", "account", routeValues);
        originalHandler.Invoke(context);
    };

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString(url.Action("login", "account")),
        //Set the Provider
        Provider = provider
    });
}

另见这段代码:

希望它能满足您的需求。

更新: 为了减少混淆,我更新了我的答案以使用@Lafis 增强功能,而不是使用包装类来应用扩展行为。投票时也请感谢@Lafis。

关于c# - MVC 5 如何使用本地化路由定义 Owin LoginPath,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21168955/

相关文章:

c# - 日志属性未记录在 Serilog 中

带边界的 C# HTTP POST

c# - ASP.NET MVC Html.Editor 将模型传递给编辑器模板

c# - MVC5 将身份验证表单放在 web.config 中的什么位置?

asp.net - 在 ASP.NET OWIN OpenIdConnect 代码授权流程中用基于 token 的身份验证替换 Cookie

c# - .NET Framework 中的“AssemblyTitle”属性

c# - 传递结构是否比传递其成员占用更多的内存/开销?

javascript - 未经授权的 AJAX 请求返回状态代码 200 而不是 401

asp.net-mvc - 使用 OWIN 将 ASP.NET MVC 应用程序连接到 Azure AD 或使用默认模板

c# - 如果通过主机名访问 API,RestSharp 和 NTLM 身份验证不起作用