Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC: How to default to a page given certain condition?

I have a class called PasswordChangeChecker.csthat has a method that returns from the database whether or not a user has changed their password. The signature for that method is:

public bool IsPasswordChangedFromInitial(string IdOfUser)

where IdOfUser is the Id field from the Identity framework User. If it returns true, that means the change password page should not be displayed, otherwise, it should navigate to the change password form. Once the user successfully changes their password, the database flag gets set appropriately, and they should not be prompted for a password change again (unless manually forced to by an admin). How can I put this method in the RouteConfig.cs file, where currently I have:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

    namespace IdentityDevelopment
    {
        public class RouteConfig
        {
            public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

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

How can I add a conditional construct into the defaults parameter so I can use the IsPasswordChangedFromInitial method to decide whether or not to go to the password change page? That page is at /Account/ChangePassword.

EDIT

As per the comments, the appropriate action methods for my specific need are (I have omitted irrelevant code):

Login post action:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginModel details, string returnUrl)
            {

                if (ModelState.IsValid)
                {
                    AppUser user = await UserManager.FindAsync(details.Name,
                        details.Password);
                    if (user == null)
                    {
                        AppUser userByName = await UserManager.FindByNameAsync(details.Name);
                        if(userByName == null)
                        {
                            ModelState.AddModelError("", "Invalid username.");
                        }
                        else
                        {
                            //If this else is reached, it means the password entered is invalid.
                           //code for incrementing count of failed attempts and navigation to lock out page if needed

                        }
                    }
                    else
                    {
                        if(user.LockedOut)
                        {
                            //navigate to locked out page
                        }
                        else
                        {
                            PasswordChangeChecker PassCheck = new PasswordChangeChecker();
                            string userId = user.Id.ToString();
                            bool proceed = PassCheck.IsPasswordChangedFromInitial(userId);

                            //Authorize the user
                            ClaimsIdentity ident = await UserManager.CreateIdentityAsync(user,
                                                     DefaultAuthenticationTypes.ApplicationCookie);
                            ident.AddClaims(LocationClaimsProvider.GetClaims(ident));
                            ident.AddClaims(ClaimsRoles.CreateRolesFromClaims(ident));
                            AuthManager.SignOut();
                            AuthManager.SignIn(new AuthenticationProperties
                            {
                                IsPersistent = false
                            }, ident);

                            //persist login into db code


                            if (proceed)
                            {

                                //reset failed logins count
                                return Redirect(returnUrl);
                            }
                            else
                            {
                                return ChangePassword();
                            }
                        }


                    }
                }
                ViewBag.returnUrl = returnUrl;
                return View(details);
            }

ChangePassword() get action:

[HttpGet]
[Authorize]
public ActionResult ChangePassword()
{
   return View();             
}

Somehow the view returned is the view in the RouteConfig.cs instead of the ChangePassword.cshtml page. Thank you.

like image 441
ITWorker Avatar asked Oct 13 '16 15:10

ITWorker


1 Answers

I would do it with global action filters

you can make a action filter with method

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    if (showChagePwPage)
    {
        //redirect to the change password page
        filterContext.Result = new RedirectToActionResult("ChangePassword", "Account");
    }

    base.OnActionExecuting(filterContext);
}

and then adding it into global action filter by

GlobalFilters.Filters.Add(yourFilterContext);
like image 134
Steve Avatar answered Nov 04 '22 03:11

Steve