Where is the entry point for ASP.NET MVC’s HttpContext

asp.netasp.net-mvc

I've got some custom FormsAuthentication with a custom AuthorizeAttribute where I'm maintaining the cookie manually, but I'm doing it within the filter's context.

What I want to do is move this to the very beginning entry point, at the very beginning of the request's life, and only do it once, and not rely on an attribute kicking it off.

But, I don't know where that would be. MVC's page lifecycle is very different than the WebForms lifecycle, so its not as cut and dry as subscribing to one of WebForm's page lifecycle events.

So in ASP.NET MVC, where does the HttpContext begin?

Best Answer

Update:

With more digging into this I came across Cephas Lin's excellent article and PDF of ASP.NET MVC 5's lifecycle.

The PDF contains two images that clearly portray the flow of the MVC 5's lifecycle. The first gives a 10,000 foot perspective of it all. The second image is very detailed and much too large to share here.

The first image:

enter image description here

My workaround:

After doing some digging I've pieced together somewhat of a workaround. Two Authorization filters that are executed in different orders.

MVC filters have an order of operation based on Eranga's answer to this question: https://stackoverflow.com/questions/6561883/in-what-order-are-filters-executed-in-asp-net-mvc

Eranga wrote:

Filters run in the following order:

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

For example, authorization filters run first and exception filters run last. Within each filter type, the Order value specifies the run order. Within each filter type and order, the Scope enumeration value specifies the order for filters. This enumeration defines the following filter scope values (in the order in which they run):

  1. First
  2. Global
  3. Controller
  4. Action
  5. Last

Extracted from MSDN

With this knowledge, I've implemented a second Authorization attribute LoadAuthCookie which handles loading the cookie, fetching the current user's relevant role/permission data into a custom IPrincipal and IIdentity, and assigning the current HttpContext's user to this IPrincipal.

The LoadAuthCookie attribute only loads the cookie data if it exists and does not handle redirection or any other Authorization logic, and is registered within RegisterGlobalFilters.

Starting from Global.asax:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        /* other global stuff */
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        /* other global stuff */
    }
}

And then

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new LoadAuthCookie());
}

This registers LoadAuthCookie attribute not only before, but also at a higher order of operation than the other Authorization attributes.

Then my other Authorization attribute, CustomAuthorize, can be applied at the Controller/Action level, and always fires after the auth cookie has been loaded, so has access to all of the nice things in the custom IPrincipal.

[CustomAuthorize(Role=Role.Admin)]
public class AdminController : ControllerBase
{
    public ActionResult Index()
    {
        return View();
    }
}

However this probably isn't ideal, and a custom Authentication filter will be the place to load the auth cookie, instead of a custom Authorization filter. Authentication happens before Authorization.