如何为所有控制器仅应用一次覆盖方法

How to Apply Override Method only once for all controller

我正在尝试实现以下逻辑:

每当创建新用户时,都会分配一个默认的硬编码密码。如果新创建的用户登录,系统将强制用户更改其默认密码

我已经在我的控制器中使用这段代码成功实现了上述逻辑:

protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //Check if authenticated
        if (filterContext.HttpContext.User.Identity.IsAuthenticated && !filterContext.HttpContext.Request.RawUrl.Equals("/Account/ChangePassword") && !filterContext.HttpContext.Request.RawUrl.Equals("/Account/LogOff"))
        {
            //Get user Data
            MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
            if (currentUser.GetPassword().Equals("password"))
            {
                filterContext.Result = new RedirectToRouteResult(
                                       new RouteValueDictionary 
                                        { 
                                            { "controller", "Account" }, 
                                            { "action", "ChangePassword" } 
                                        });
            }
        }
    }

但是,现在我必须将这段代码复制粘贴到我所有的控制器上。这是否不尊重 mvc3 中的 DRY 原则?

如果是,我应该将此代码放在哪里或如何放置,以便它可以全局实施到我的所有控制器? 我试图将其粘贴到 Global.asax 中,但出现错误 "No Suitable Method Found to Override"

正如其他人之前在评论部分所述,您可以使用 base controller 或使用 动作过滤器.

目前,您可以考虑使用像这样创建的 actionfilter。

public class YourActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {

    }
}


     [YourActionFilter]
     public class HomeController : Controller
     {
          public ActionResult Index()
          {
               return View();
          }

          public ActionResult About()
          {
               return View();
          }
     }

您可以在 MS doc

中找到更多详细信息

使用全局过滤器。这是动作过滤器的示例。

public class ForceLoginActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
    }

    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //Check if authenticated
        if (filterContext.HttpContext.User.Identity.IsAuthenticated && !filterContext.HttpContext.Request.RawUrl.Equals("/Account/ChangePassword") && !filterContext.HttpContext.Request.RawUrl.Equals("/Account/LogOff"))
        {
            //Get user Data
            MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
            if (currentUser.GetPassword().Equals("password"))
            {
                filterContext.Result = new RedirectToRouteResult(
                                       new RouteValueDictionary
                                        {
                                        { "controller", "Account" },
                                        { "action", "ChangePassword" }
                                        });
            }
        }
    }
}

用法

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new ForceLoginActionFilter());
    }
}

参考:Filtering in ASP.NET MVC

NOTE: Never use a base controller in ASP.NET MVC. This will almost always lead to creating a god object that is difficult to maintain.