简体   繁体   English

需要针对多种不同情况在ASP.NET MVC站点上进行全局定向重定向的建议

[英]Need recommendation for global, targeted redirects on ASP.NET MVC site for multiple differing conditions

I'm working on an ASP.NET MVC application where administrators can add new users and flag them to complete additional information before they can use other features of the site. 我正在使用ASP.NET MVC应用程序,管理员可以在其中添加新用户并标记他们以完成其他信息,然后他们才能使用网站的其他功能。 For example, we have a "ForcePasswordReset" bool, and a requirement to complete Security Questions. 例如,我们有一个“ ForcePasswordReset”布尔值,以及完成安全问题的要求。 We're not using Active Directory for these users. 我们没有为这些用户使用Active Directory。

Ultimately this is the behavior I'd like to implement: 最终,这是我想要实现的行为:

  1. Direct any logged in user who is required to change password to the ChangePassword view. 将需要更改密码的所有已登录用户定向到ChangePassword视图。 And if that user clicks on other links, funnel him back to the ChangePassword view. 并且,如果该用户单击其他链接,则将其引导回ChangePassword视图。
  2. Same scenario for users who must change their security questions. 对于必须更改其安全性问题的用户,情况相同。

Initially I placed the checks directly into a Login Controller ActionResult. 最初,我将支票直接放入Login Controller ActionResult中。 But this only accounts for the Login action. 但这仅解释了登录操作。 An abbreviated code sample is below. 下面是一个简短的代码示例。

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);
        }
    }

One problem with this approach is that there are other hyperlinks presented in those targeted views, where the user could navigate away from the targeted interface. 这种方法的一个问题是,在那些目标视图中还存在其他超链接,用户可以在其中导航离开目标界面。 So for example, a user directed to the ChangeSecurityQuestions view could just click away from it. 因此,例如,定向到ChangeSecurityQuestions视图的用户只需单击即可。

Logged-in users can change those settings at any time. 登录的用户可以随时更改这些设置。 I could create duplicate views for changing passwords and security questions that are fashioned just for this scenario, where the user is being forced to update these values. 我可以为更改密码和安全性问题创建重复的视图,这些视图仅适用于这种情况,在这种情况下,用户被迫更新这些值。 In the interest of staying DRY and reducing maintenance, I'd like to use the same views for both scenarios (users who just want to edit that info, and users who are being forced to edit that info). 为了保持DRY并减少维护,我想在两种情况下使用相同的视图(仅想编辑该信息的用户和被迫编辑该信息的用户)。 But, trying to stay DRY in this respect may be wrongheaded if the alternative is worse. 但是,如果替代方案更糟,尝试在这方面保持DRY可能会出错。

I started to write a method within a helper class to divert these users, trying something like this. 我开始在助手类中编写一种方法来转移这些用户的权限,尝试类似的方法。

    /// <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");
    }

But that RedirectToAction is inaccessible due to protection level. 但是由于保护级别的原因,该RedirectToAction无法访问。 Moreover, that doesn't appear to be recommended ( Is it possible to use RedirectToAction() inside a custom AuthorizeAttribute class? ). 而且,似乎不建议这样做( 是否可以在自定义AuthorizeAttribute类内使用RedirectToAction()? )。 And I don't like the idea of junking up my controllers by pasting this check all over the place. 而且我不喜欢通过在整个地方粘贴此检查来增加我的控制器的想法。

UtilityHelpers.divertExternalUserAsRequired(this, externalUser);

What is the recommended approach to handling this scenario? 建议使用什么方法来处理这种情况? I would perfer something that's more globally implemented, where the check can run when any relevant view loads. 我认为这是在全局范围内实现的,可以在加载任何相关视图时运行检查。

Thanks for your help. 谢谢你的帮助。

If I'm understanding your question correctly then you've got a few options available to you. 如果我正确理解了您的问题,那么您可以使用几种选择。

One option is to check the necessary conditions within Application_BeginRequest in your Global.asax.cs class. 一种选择是检查Global.asax.cs类中Application_BeginRequest中的必要条件。 This method is called at the very beginning of every request and if the condition fails then you can load a different controller action like so: 在每个请求的开始都会调用此方法,如果条件失败,则可以像下面这样加载其他控制器操作:

    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();
        }
    }

Another option available to you is to create and register a global action filter . 您可以使用的另一种选择是创建并注册全局动作过滤器 As you mentioned in your question, you don't like the idea of littering your controllers with these condition checks. 正如您在问题中提到的那样,您不喜欢用这些条件检查乱扔控制器的想法。 By registering a global action filter your controllers can remain completely unaware of the action filter being performed against it. 通过注册全局动作过滤器,您的控制器可以完全不知道针对它执行的动作过滤器。 All you need to do is register your action filter within Global.asax.cs like so: 您需要做的就是在Global.asax.cs注册操作过滤器,如下所示:

protected void Application_Start()
{
    ...

    GlobalFilters.Filters.Add(new SecurityQuestionCompleteFilter());

    ...
}

I hope this helps. 我希望这有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM