ASP.. NET MVC:如何在给定条件下默认为页面

本文关键字:条件下 默认 MVC NET ASP | 更新日期: 2023-09-27 18:13:07

我有一个名为PasswordChangeChecker.cs的类,它有一个从数据库返回用户是否更改了密码的方法。该方法的签名是:

public bool IsPasswordChangedFromInitial(string IdOfUser)

其中IdOfUser为Identity框架User的Id字段。如果它返回true,这意味着不应该显示更改密码页面,否则,它应该导航到更改密码表单。一旦用户成功地更改了密码,数据库标志将被适当地设置,并且不应该再次提示他们更改密码(除非由管理员手动强制执行)。我如何将此方法放在RouteConfig.cs文件中,目前我有:

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

我如何将条件构造添加到defaults参数中,以便我可以使用IsPasswordChangedFromInitial方法来决定是否进入密码更改页面?那一页在/Account/ChangePassword

编辑

根据注释,适合我特定需求的操作方法是(我省略了不相关的代码):

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

返回的视图是RouteConfig.cs而不是ChangePassword.cshtml页面中的视图。谢谢你。

ASP.. NET MVC:如何在给定条件下默认为页面

我会使用全局动作过滤器

你可以用方法

创建一个动作过滤器
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    if (showChagePwPage)
    {
        //redirect to the change password page
        filterContext.Result = new RedirectToActionResult("ChangePassword", "Account");
    }
    base.OnActionExecuting(filterContext);
}

,然后通过

将其添加到全局动作过滤器中
GlobalFilters.Filters.Add(yourFilterContext);

经过几天类似于您的这种地狱般的练习后,我试图在登录时路由用户,我意识到我将无法在登录Account控制器时获得UserId的值。我做了一些实验,想出了这个方法,解决了我的问题。

我在我的Home控制器中创建了一个ActionResult,并将其命名为Purgatory(当然,当它被证明具有功能时,我将其重命名为更合适的名称)。在这里,我填充了所有登录逻辑,以便在登录时将登录用户路由到各自的页面。

然后,在帐户控制器中的redirecttollocal中,我更改了
return RedirectToAction("Index", "Home");

return RedirectToAction("Purgatory", "Home");

所以现在当用户登录时,如果returnTo参数没有设置为特定的页面,则returnTo参数将为空,当它到达redirecttollocal时,它将下降到以前的主页重定向,现在将进入炼狱。

这听起来是使用动作过滤器的好时机,您可以全局或每个控制器/动作应用它。

下面是一个简单的例子:

using System;
using System.Web.Mvc;
using System.Web.Routing;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class VerifyPasswordChangedAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if(!filterContext.ActionDescriptor.ActionName.Equals("changepassword", StringComparison.OrdinalIgnoreCase))
        {
            if (filterContext.HttpContext.Request.IsAuthenticated)
            {
                var userName = filterContext.HttpContext.User.Identity.Name;
                PasswordChangeChecker PassCheck = new PasswordChangeChecker();
                if (!PassCheck.IsPasswordChangedFromInitial(userName))
                {
                    filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "account", action = "changepassword", area = string.Empty }));
                }
            }
        }
        base.OnActionExecuting(filterContext);
    }
}

我会修改您的IsPasswordChangedFromInitial方法,以简单地使用经过身份验证的用户的用户名,而不是试图找出如何在操作过滤器中访问UserManager实例。否则,假设您使用的是基于owin的ASP。. NET Identity,当你创建ClaimsIdentity时,添加一个声明来存储user.Id字段,这样你就不必一直查找它了。

最外面的条件处理全局过滤器的情况—没有它,您将获得无限重定向。