我有一个 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/