15

I have a scenario whereby with every page request I must check the session of the presence of a particular ID. If this is found I must grab a related object from the database and make it available to the controller. If no session ID is found I need to redirect the user (session expired).

At the moment I have a custom chunk of code (couple of lines) that does this at the start of every action method within my controller - which seems like unnecessary repetition.

Is this scenario worthy of an Action Filter?

Thanks

UPDATE Some great info here guys. Thank you

Sergio
  • 9,761
  • 16
  • 60
  • 88

3 Answers3

10

Yes, this sounds like a good application of an action filter, as you can apply it at the controller level to operate on all actions. You could also make it part of a controller base class, if you didn't want to add it to all controllers manually, or write your own controller factory which automatically applies this action filter to each controller.

See ASP.NET MVC Pass object from Custom Action Filter to Action for passing data from an action filter to an action.

Community
  • 1
  • 1
devdigital
  • 34,151
  • 9
  • 98
  • 120
  • +1 and thank you for the link in your second paragraph - took me right to what I needed for a similar problem. – Funka Mar 07 '13 at 02:10
9

Create a base controller like this

   public class MyContollerController : Controller
    {
        public DataEntity userData;
        protected override void Initialize(System.Web.Routing.RequestContext requestContext)
        {            
            base.Initialize(requestContext);
            var customId = requestContext.HttpContext.Session["key"];
            if(customId!=null)
            {
                 userData=getDataGromDataBase(customId);
            }   
            else
            {
               //redirect User
            }     
        }
    }

Now Create ur controllers like this

public class MyDemoController : MyContollerController
{
        public ActionResult Action1()
        { 
             //access your data
             this.userData

        }
        public ActionResult Action2()
        { 
             //access your data
             this.userData

        }
}
Praveen Prasad
  • 31,561
  • 18
  • 73
  • 106
  • 1
    I've been using MVC for almost four years now and never knew about the `Initialize` method, so thank you! I've always been shoving this kind of logic into my base controller's `OnActionExecuting` method, but now I see that `Initialize` seems more ... ideal. This is because as we all should know, the constructor fails us as not all controller properties are fully ready by the time it is called. For the lazy, Intellisense on `Initialize` says "Initializes data that might not be available when the constructor is called." Again, thank you! – Funka Mar 07 '13 at 02:07
3

Another way is to do that with Model Binders. Suppose that object is ShoppingCart

//Custom Model Binder
public class ShoppingCarModelBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            //TODO: retrieve model or return null;
        }
    }
 //register that binder in global.asax in application start

ModelBinders.Binders.Add(typeof(ShoppingCart), new ShoppingCartBinder());

// controller action

public ActionResult DoStuff(ShoppingCart cart)
{
     if(cart == null)
     {
     //whatever you do when cart is null, redirect. etc
     }
     else
     {
     // do stuff with cart
     }
}

Moreover, this is more unit testable and clear way, as this way action relies on parameters supplied from outside

archil
  • 39,013
  • 7
  • 65
  • 82