Question

I have a subscription based MVC 2 application with the basic .NET Membership service in place (underneath some custom components to manage the account/subscription, etc). Users whose accounts have lapsed, or who have manually suspended their accounts, need to be able to get to a single view in the system that manages the status of their account. The controller driving that view is protected using the [Authorize] attribute.

I want to ensure that no other views in the system can be accessed until the user has re-activated their account. In my base controller (from which all my protected controllers derive) I tried modifying the OnActionExecuting method to intercept the action, check for a suspended account, and if it's suspended, redirect to the single view that manages the account status. But this puts me in an infinite loop. When the new action is hit, OnActionExecuting gets called again, and the cycle keeps going.

I don't really want to extend the [Authorize] attribute, but can if need be.

Any other thoughts on how to do this at the controller level?

EDIT: in the base controller, I was managing the redirect (that subsequently created the redirect loop) by modifying the filterContext.Result property, setting it to the RedirectToAction result of my view in question. I noticed everytime the loop occurs, filterContext.Result == null. Perhaps I should be checking against a different part of filterContext?

Was it helpful?

Solution

Ok, so here's my solution in case it helps anyone else. There's got to be a more elegant way to do this, and I'm all ears if anyone has a better idea.

In my BaseController.cs:

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        ViewData["CurrentUser"] = CurrentUser; // this is a public property in the BaseController

        if (CurrentUser != null && CurrentUser.Account.Status != AccountStatus.Active)
        {
            // if the account is disabled and they are authenticated, we need to allow them
            // to get to the account settings screen where they can re-activate, as well as the logoff
            // action.  Everything else should be disabled.
            string[] actionWhiteList = new string[] { 
                Url.Action("Edit", "AccountSettings", new { id = CurrentUser.Account.Id, section = "billing" }), 
                Url.Action("Logoff", "Account")
            };

            var allowAccess = false;
            foreach (string url in actionWhiteList)
            {
                // compare each of the whitelisted paths to the raw url from the Request context.
                if (url == filterContext.HttpContext.Request.RawUrl)
                {
                    allowAccess = true;
                    break;
                }
            }

            if (!allowAccess)
            {
                filterContext.Result = RedirectToAction("Edit", "AccountSettings", new { id = CurrentUser.Account.Id, section = "billing" });
            }
        }

        base.OnActionExecuting(filterContext);
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top