Search code examples
c#asp.net-mvccontrolleraction-filterauthorize-attribute

ActionFilter and Authorize Attribute in MVC causing object reference error


I am using MVC4 to build ASP.NET application. I am using ActionFilterAttribute and AuthorizeAttribute in my business logic. Following is sample code

Controller Class

[SessionExpire]
[AuthorizeSubscription]
public class StoreController : Controller
{
    public ActionResult StoreDetail()
    {
       // My logic goes here
    }

    [AuthorizeProductEdit]
    [HttpGet]
    public ActionResult EditProduct()
    {
       // My logic goes here
    }

If we look at the code, I have first used SessionExpire attribute that inherit ActionFilterAttribute class, It check if session is valid for current request and do some redirection there. Next, i am checking AuthorizeSubscription attribute that inherit AuthorizeAttribute class. It also do some redirection based on logic written over there.

In EditProduct Action, i have used another AuthorizeAttribute.

If I hit url for StoreDetail Action without making any session, it redirect me to desired page.

But if i hit url for EditProduct Action, It throws me Object Reference error. During debug It first goes into the code for AuthorizeProdcutEdit and there fail for finding Session Null.

Why it is not executing SessionExpire code first and exit from there if found Session Null ?


Solution

  • Per MSDN:

    Filters run in the following order:

    1. Authorization filters
    2. Action filters
    3. Response filters
    4. Exception filters

    The reason your SessionExpire attribute fires after your AuthorizeSubscription attribute is because MVC always fires Authorization filters first.

    So to fix that problem, you need your SessionExpire to implement IAuthorizationFilter (and presumably inherit Attribute).

    In addition, you will need to set the order of your attributes, because the .NET framework does not guarantee which order they will be processed in.

    [SessionExpire(Order=1)]
    [AuthorizeSubscription(Order=2)]
    public class StoreController : Controller
    {
       // Remaining implementation...
    

    Do note that the best approach is to separate your filters from your attributes, which both allows them to be DI-friendly and also allows you to set the order explicitly by registering the filters globally in a specific order.