需要在 ASP.NET MVC 站点上针对多种不同条件推荐全局、有针对性的重定向
Need recommendation for global, targeted redirects on ASP.NET MVC site for multiple differing conditions
我正在开发一个 ASP.NET MVC 应用程序,管理员可以在其中添加新用户并标记他们以完成附加信息,然后才能使用网站的其他功能。例如,我们有一个 "ForcePasswordReset" 布尔值,以及完成安全问题的要求。我们没有为这些用户使用 Active Directory。
最终这是我想要实现的行为:
- 将任何需要更改密码的登录用户指向
更改密码视图。如果该用户点击其他链接,漏斗
他回到 ChangePassword 视图。
- 对于必须更改安全问题的用户,情况相同。
最初我将检查直接放入登录控制器 ActionResult 中。但这仅说明登录操作。下面是一个简短的代码示例。
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid)
{
// ...
// Does the user need to complete some missing information?
if (externalUser.IsSecurityQuestionInfoComplete == false)
return RedirectToAction("ChangeSecurityQuestions", "MyInfo");
if (externalUser.ForcePasswordReset)
return RedirectToAction("ChangePassword", "MyInfo");
// Login was successful
return RedirectToLocal(returnUrl);
}
}
这种方法的一个问题是在那些目标视图中存在其他超链接,用户可以在这些视图中导航离开目标界面。因此,例如,指向 ChangeSecurityQuestions 视图的用户只需单击即可离开它。
登录用户可以随时更改这些设置。我可以创建重复的视图来更改密码和安全问题,这些视图专为这种情况而设计,用户被迫更新这些值。为了保持 DRY 和减少维护,我想在两种情况下使用相同的视图(只想编辑该信息的用户,以及被迫编辑该信息的用户)。但是,如果替代方案更糟,那么在这方面试图保持 DRY 可能是错误的。
我开始在helper中写一个方法class来转移这些用户,尝试类似的东西。
/// <summary>
/// Check scenarios where the ExternalUser needs to complete some missing information, and divert as necessary.
/// </summary>
public static void divertExternalUserAsRequired(Controller controller, ExternalUser externalUser)
{
if (externalUser.IsSecurityQuestionInfoComplete == false)
return controller.RedirectToAction("ChangeSecurityQuestions", "MyInfo");
if (externalUser.ForcePasswordReset)
return controller.RedirectToAction("ChangePassword", "MyInfo");
}
但是由于保护级别,RedirectToAction 无法访问。此外,似乎不推荐这样做 (Is it possible to use RedirectToAction() inside a custom AuthorizeAttribute class?)。而且我不喜欢通过将此检查到处粘贴来破坏我的控制器的想法。
UtilityHelpers.divertExternalUserAsRequired(this, externalUser);
处理这种情况的推荐方法是什么?我更喜欢更全局实施的东西,在任何相关视图加载时检查可以 运行 。
感谢您的帮助。
如果我没有正确理解你的问题,那么你有几个选项可供选择。
一个选项是在 Global.asax.cs
class 中检查 Application_BeginRequest
内的必要条件。这个方法在每个请求的最开始被调用,如果条件失败,那么你可以像这样加载一个不同的控制器动作:
protected void Application_BeginRequest(object sender, EventArgs e)
{
if (!externalUser.IsSecurityQuestionInfoComplete)
{
var routeData = new RouteData();
routeData.Values["action"] = "MyInfo";
routeData.Values["controller"] = "ChangeSecurityQuestions";
RequestContext requestContext = new RequestContext(new HttpContextWrapper(Context), routeData);
IController errorController = new ChangeSecurityQuestionsController();
errorController.Execute(requestContext);
requestContext.HttpContext.Response.End();
}
}
您可以使用的另一个选项是创建和注册 global action filter。正如您在问题中提到的,您不喜欢用这些条件检查来乱丢控制器的想法。通过注册全局动作过滤器,您的控制器可以完全不知道针对它执行的动作过滤器。您需要做的就是在 Global.asax.cs
中注册您的操作过滤器,如下所示:
protected void Application_Start()
{
...
GlobalFilters.Filters.Add(new SecurityQuestionCompleteFilter());
...
}
希望对您有所帮助。
我正在开发一个 ASP.NET MVC 应用程序,管理员可以在其中添加新用户并标记他们以完成附加信息,然后才能使用网站的其他功能。例如,我们有一个 "ForcePasswordReset" 布尔值,以及完成安全问题的要求。我们没有为这些用户使用 Active Directory。
最终这是我想要实现的行为:
- 将任何需要更改密码的登录用户指向 更改密码视图。如果该用户点击其他链接,漏斗 他回到 ChangePassword 视图。
- 对于必须更改安全问题的用户,情况相同。
最初我将检查直接放入登录控制器 ActionResult 中。但这仅说明登录操作。下面是一个简短的代码示例。
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid)
{
// ...
// Does the user need to complete some missing information?
if (externalUser.IsSecurityQuestionInfoComplete == false)
return RedirectToAction("ChangeSecurityQuestions", "MyInfo");
if (externalUser.ForcePasswordReset)
return RedirectToAction("ChangePassword", "MyInfo");
// Login was successful
return RedirectToLocal(returnUrl);
}
}
这种方法的一个问题是在那些目标视图中存在其他超链接,用户可以在这些视图中导航离开目标界面。因此,例如,指向 ChangeSecurityQuestions 视图的用户只需单击即可离开它。
登录用户可以随时更改这些设置。我可以创建重复的视图来更改密码和安全问题,这些视图专为这种情况而设计,用户被迫更新这些值。为了保持 DRY 和减少维护,我想在两种情况下使用相同的视图(只想编辑该信息的用户,以及被迫编辑该信息的用户)。但是,如果替代方案更糟,那么在这方面试图保持 DRY 可能是错误的。
我开始在helper中写一个方法class来转移这些用户,尝试类似的东西。
/// <summary>
/// Check scenarios where the ExternalUser needs to complete some missing information, and divert as necessary.
/// </summary>
public static void divertExternalUserAsRequired(Controller controller, ExternalUser externalUser)
{
if (externalUser.IsSecurityQuestionInfoComplete == false)
return controller.RedirectToAction("ChangeSecurityQuestions", "MyInfo");
if (externalUser.ForcePasswordReset)
return controller.RedirectToAction("ChangePassword", "MyInfo");
}
但是由于保护级别,RedirectToAction 无法访问。此外,似乎不推荐这样做 (Is it possible to use RedirectToAction() inside a custom AuthorizeAttribute class?)。而且我不喜欢通过将此检查到处粘贴来破坏我的控制器的想法。
UtilityHelpers.divertExternalUserAsRequired(this, externalUser);
处理这种情况的推荐方法是什么?我更喜欢更全局实施的东西,在任何相关视图加载时检查可以 运行 。
感谢您的帮助。
如果我没有正确理解你的问题,那么你有几个选项可供选择。
一个选项是在 Global.asax.cs
class 中检查 Application_BeginRequest
内的必要条件。这个方法在每个请求的最开始被调用,如果条件失败,那么你可以像这样加载一个不同的控制器动作:
protected void Application_BeginRequest(object sender, EventArgs e)
{
if (!externalUser.IsSecurityQuestionInfoComplete)
{
var routeData = new RouteData();
routeData.Values["action"] = "MyInfo";
routeData.Values["controller"] = "ChangeSecurityQuestions";
RequestContext requestContext = new RequestContext(new HttpContextWrapper(Context), routeData);
IController errorController = new ChangeSecurityQuestionsController();
errorController.Execute(requestContext);
requestContext.HttpContext.Response.End();
}
}
您可以使用的另一个选项是创建和注册 global action filter。正如您在问题中提到的,您不喜欢用这些条件检查来乱丢控制器的想法。通过注册全局动作过滤器,您的控制器可以完全不知道针对它执行的动作过滤器。您需要做的就是在 Global.asax.cs
中注册您的操作过滤器,如下所示:
protected void Application_Start()
{
...
GlobalFilters.Filters.Add(new SecurityQuestionCompleteFilter());
...
}
希望对您有所帮助。