C# 我应该在哪里编写代码来覆盖MVC请求的路由数据值?
我想根据C# 我应该在哪里编写代码来覆盖MVC请求的路由数据值?,c#,asp.net-mvc,asp.net-mvc-5,asp.net-mvc-routing,C#,Asp.net Mvc,Asp.net Mvc 5,Asp.net Mvc Routing,我想根据user.Identity中的用户claim覆盖RouteData中名为lang的项的值 例如,如果路由数据中的lang值为en(example.com/en/login),我希望读取用户的lang声明,并通过它覆盖roue数据中的lang。因此,登录页面中的其他链接应遵循新的lang值(而不是en) 设置语言的位置: 在我的项目中,我在应用程序中设置了UiThread的语言\u AuthenticateRequest。因此,我在那里更改了lang路由值,但似乎没有达到预期的结果(为什么
user.Identity
中的用户claim
覆盖RouteData
中名为lang
的项的值
例如,如果路由数据中的lang
值为en
(example.com/en/login),我希望读取用户的lang
声明
,并通过它覆盖roue数据中的lang
。因此,登录页面中的其他链接应遵循新的lang
值(而不是en
)
设置语言的位置:
在我的项目中,我在应用程序中设置了UiThread
的语言\u AuthenticateRequest
。因此,我在那里更改了lang
路由值,但似乎没有达到预期的结果(为什么?):
我应该在哪里编写代码来覆盖请求的路由值?您的建议是什么?创建一个实现
IActionFilter
的类,覆盖其中的“lang”值,并将MVC配置为使用该IActionFilter
using System.Web.Mvc;
namespace WebApplication1.Filters
{
public class LangOverrideFilter : IActionFilter
{
public void OnActionExecuted(ActionExecutedContext filterContext)
{
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.RouteData.Values["lang"] = "en";
//Access userclaims through filterContext.HttpContext.User.
}
}
}
在App_Start/FilterConfig.cs中:
using System.Web;
using System.Web.Mvc;
using WebApplication1.Filters;
namespace WebApplication1
{
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new LangOverrideFilter());
filters.Add(new HandleErrorAttribute());
}
}
}
用于测试的My App_Start/RouteConfig.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace WebApplication1
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{lang}/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
应用程序\u AuthenticateRequest
在中太晚,无法对路由值产生任何影响
MVC使用在动作过滤器运行之前的请求的早期解析ModelBinder中的值,因此动作过滤器不是解决此问题的方法
你基本上有两个选择
路线
或。路由负责将请求转换为路由值,因此您可以在此处放置条件逻辑来构建请求IAuthorizationFilter
。授权筛选器在ModelBinder之前运行,因此会影响传递到模型和操作方法中的值www.somesite.com
进入您的网站,在这种情况下,他们不会使用自己的语言。他们将毫无问题地认识到他们看到的是错误的语言,并将立即寻找某种语言下拉列表或标志图标以切换到他们的语言。除非您正在使用某种“记住我”功能,否则此步骤将始终在他们登录之前进行RedirectToAction
,以便在登录时将它们重定向到具有新区域性的URL。这将允许您(现在感到沮丧)的用户能够覆盖您的覆盖,并更改回他们想要查看站点的语言
如果您在URL或某种语言选择器中选择网站,而不给他们以所需语言查看网站的选项,那么当他们没有返回时,不要感到惊讶
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
// Change to the culture of the signed in user by replacing the
// first segment of the URL.
returnUrl = ChangeCultureInUrl(returnUrl);
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
[HttpPost]
[异名]
[ValidateAntiForgeryToken]
公共异步任务登录(LoginView模型,字符串返回URL)
{
如果(!ModelState.IsValid)
{
返回视图(模型);
}
//这不会将登录失败计入帐户锁定
//要使密码失败触发帐户锁定,请更改为shouldLockout:true
var result=wait SignInManager.PasswordSignInAsync(model.Email、model.Password、model.RememberMe、shouldllockout:false);
开关(结果)
{
案例标志状态成功:
//通过替换
//URL的第一段。
returnUrl=ChangeCultureInUrl(returnUrl);
返回重定向到本地(returnUrl);
案例标志状态锁定输出:
返回视图(“锁定”);
案例标志状态。要求验证:
return RedirectToAction(“SendCode”,new{ReturnUrl=ReturnUrl,RememberMe=model.RememberMe});
案例信号状态故障:
违约:
AddModelError(“,”登录尝试无效“);
返回视图(模型);
}
}
同样,我的建议是让用户选择他们的区域性,但是如果您仍然认为出于某种原因这是必要的,那么上述解决方案要比劫持区域性并从用户手中取得控制权要好得多。您应该能够在
ActionFilter
中做到这一点。从请求语言的用户手中夺走对所请求语言的控制权似乎是一个非常糟糕的主意。这只会让那些想用一种语言查看网站的用户感到沮丧,但这不允许他们使用,因为该语言与他们在URL中请求的语言不同。请参阅和。@NightOwl888,我的站点中有一个场景,我认为用户希望进行此更改:有时用户在站点中使用一种语言(例如,不是他最喜欢的语言)
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
// Change to the culture of the signed in user by replacing the
// first segment of the URL.
returnUrl = ChangeCultureInUrl(returnUrl);
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}