【问题标题】:Redirect from Controller Initialize not working从控制器初始化重定向不起作用
【发布时间】:2011-11-22 11:19:21
【问题描述】:

我已经覆盖了检查某些会话数据是否存在的控制器。存储库需要此数据才能正常工作,因此如果它不存在,则应在检查后注销用户。

protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
    base.Initialize(requestContext);
    if (Session["CompanyID"] != null)
    {
        repo.CompanyID = (long)Session["CompanyID"];
    }
    else
    {
        RedirectToAction("LogOff", "Account");
    }
}

我的代码看起来像这样,但是即使调用了 RedirectToAction,控制器仍然会打开默认操作并且用户没有注销。 你能推荐一下如何处理这个问题吗?

我以这种方式使用此会话数据,因为这是我知道的第一个可以访问它的地方,在这里我可以检查此特定数据是否存在。它是在用户登录时写入的。

此数据是数据库中用户的一部分。我已经创建了一个自定义成员和角色提供者。有没有办法以某种方式将此数据添加到 MembershipUser 类型的“用户”,以便可以在构造函数中访问它,如用户用户名?

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-3 controller asp.net-membership session-variables


    【解决方案1】:

    考虑改用自定义ActionFilter

    public class HasCompanyIdAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.HttpContext.Session["CompanyID"] == null)
            {
                filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new {action = "LogOff", controller = "Account"}));
            }
        }
    }
    

    然后可以这样应用:

    [HasCompanyId]
    public class MyController : Controller 
    {
        public ActionResult SomeAction()
        {
            return View();
        }
    }
    

    这将为 MyController(或其子类)处理的所有请求应用该属性。

    【讨论】:

    • 原理明白了,但是好像有点不切实际。由于有公共应用领域,我无法将其设为全局过滤器,然后我必须将其应用于需要它的区域内的每个操作?初始化后是否有其他方法可以中断Controller的加载并将其发送到另一个Controller的另一个动作?
    • 您可以将属性应用于控制器,它将应用于该控制器或控制器基类中的每个动作,然后该动作也将应用于每个派生类动作!跨度>
    • 嗯,这种方式仍然不能解决我必须设置一次的事实。似乎以这种方式通过FilterAttribute做事会在每次执行动作时设置它,而不是仅在实例化Controller时设置它?
    • 查看更新以了解如何应用它。是的,您需要在每次执行控制器的操作方法之一时执行检查,因为控制器的生命周期通常与会话无关。
    • 我明白你的意思了。我确实知道如何在控制器上使用过滤器。我的问题是每次应用过滤器时分配CompanyID,但后来我发现我可以保留当前的分配方式,并仅将过滤器用于 SessionAlive 检查。谢谢你,这很有帮助。
    【解决方案2】:

    只需通过覆盖基类中的 OnActionExcuting 来实现您的解决方案。然后,您可以在操作过滤器中执行您可以执行的所有操作。像这样:

    public void OnActionExecuting(ActionExecutingContext filterContext){
      if (filterContext.HttpContext.Session["CompanyID"] != null)
         repo.CompanyID = (long)filterContext.HttpContext.Session["CompanyID"];
      else
         filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new {action = "LogOff", controller = "Account"}));
    }
    

    为了简洁省略了一些代码。

    我尝试了这两种方法,发现通过操作过滤器实现它更加复杂,因为我有依赖注入要求。无论哪种方式都可以,但感觉基类方法更清晰一些。我还想在基类上设置一些属性,以使一些标准对象可用于控制器方法,以节省开发人员添加到操作中的重复代码。基类方法让这一切变得简单。

    我要补充的一个警告是,我并不是说这是一种很好的身份验证/安全方法,我纯粹是从希望在执行操作之前执行一些操作/验证的角度来看待这个问题的,而且在控制器实例上设置一些预填充的数据以遵循 DRY 原则。

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-24
      • 1970-01-01
      • 1970-01-01
      • 2020-06-26
      • 2021-01-17
      相关资源
      最近更新 更多