title: Distinguish between Web API requests and MVC requests in Application handlers
body: <p>I have a rather strange scenario. I am using autofac on a project that has both MVC4 pages and Web API endpoint. Autofac is managing the scope of my model object (which in turn manages the scope of the database context) and I have it configured for <code>InstancePerHttpRequest</code> and <code>InstancePerApiRequest</code> so that only one database context is created per request. This is so that any database objects that I use are all attached to the same request (the context is an EF6 context).</p>
  
  <p>Here is my strange scenario: The application supports a "proxying" capability where one user can become another for the duration of the page request. In order to make sure that even <code>AuthorizeAttribute</code>s pay attention to this, I am catching the request at the <code>PostAuthenticateRequest</code> event and performing the <code>IPrincipal</code> switch and also setting up the user which my database context uses. The problem comes with a permission check: I need to ask my database if a user is allowed to proxy as the user they would like to proxy as. The code is more or less as follows:</p>
  
  <pre><code>protected void Application_PostAuthenticateRequest()
  {
      if (!User.Identity.IsAuthenticated)
              return; //nothing to do here if we are not authenticated
  
      var cookie = Request.Cookies.Get(Controllers.ProxyController.ProxyCookie);
  
      //The uh-oh occurs at this line...read the rest of the question
      var model = DependencyResolver.Current.GetService&lt;Model.MyModel&gt;();
  
      //we load the user initially
      //this sets up the user for the rest of the request since our model object should be shared for everything
      var user = model.Users.Where(u =&gt; u.username == User.Identity.Name).FirstOrDefault();
      model.User.Current = model.User.Actual = user;
  
      if (cookie != null)
      {
          //we ask the database if this user can proxy as the cookie'd username
          var proxyAs = model.Users.Where(u =&gt; u.username == cookie.Value).FirstOrDefault();
          if (user != null &amp;&amp; proxyAs != null)
          {
              if (user.CanProxyAs(proxyAs))
              {
                  //this user is allowed to proxy as the specified user
                  string[] roles;
                  if (proxyAs != null)
                  {
                      //get their roles to replace ours
                      roles = proxyAs.groups.SelectMany(g =&gt; g.roles).Select(r =&gt; r.name).ToArray();
                  }
                  else
                  {
                      //no roles according to the database
                      roles = new string[0];
                  }
  
                  //set the model user stuff
                  model.User.Actual = user;
                  model.User.Current = proxyAs;
  
                  //save the original user IPrincipal
                  HttpContext.Current.Items[Controllers.ProxyController.ProxyUser] = User;
  
                  //we need to set the thread current principal as well to keep it in sync:
                  // MVC3 stuff (controllers) appears to use HttpContext.Current.User
                  // MVC4 stuff (web api) appears to use Thread.CurrentPrincipal
                  Thread.CurrentPrincipal = HttpContext.Current.User = new GenericPrincipal(new GenericIdentity(cookie.Value), roles);
              }
          }
      }
  }
  </code></pre>
  
  <p>The problem is at the part where I use the <code>DependencyResolver</code> to resolve the model object. </p>
  
  <p>This is not a problem at all for MVC requests...they use the <code>DependencyResolver</code> later to create the controllers. The <code>AutofacDependencyResolver</code> is a <code>AutofacDependencyResolver</code> as set up per the autofac MVC documentation.</p>
  
  <p>For Web API requests, however this is a problem. Since I used the <code>AutofacDependencyResolver</code> to resolve the model object in this method, an instance of the model has been instantiated for the <code>InstancePerHttpRequest</code> lifetime. However, the WebAPI is going to use <code>GlobalConfiguration.Configuration.DependencyResolver</code> which is set up as an <code>AutofacWebApiDependencyResolver</code> per the autofac Web API documentation. What ends up happening is that the model object used by a WebAPI call has not had its <code>model.User</code> property set up since the MVC <code>DependencyResolver</code> gave us back a different model.</p>
  
  <p>I could always set both objects, but then we have context issues. I never know which resolver to use: Should I use the MVC <code>DependencyResolver</code> or the Web API dependency resolver?</p>
  
  <p>Further complicating matters is the fact that the web api dependency resolver can only operate in the context of an <code>HttpRequestMessage</code> (i.e. inside an Action method). This object is not available during <code>PostAuthenticateRequest</code>.</p>
  
  <p><strong>My questions</strong></p>
  
  <p>Can I somehow tell autofac that it needs to use the same objects when resolving for both <code>InstancePerApiRequest</code> and <code>InstancePerHttpRequest</code>?</p>
  
  <p>If that is not possible, is there some way I can:</p>
  
  <ul>
  <li>Figure out if the request is an API request or MVC request and</li>
  <li>Get the <code>HttpRequestMessage</code> during <code>PostAuthenticateRequest</code> if it is an API request and use that for dependency resolution?</li>
  </ul>
  
  <p>I may also need to seriously rethink the way I am doing this since this seems at first glance to not be possible per <a href="https://stackoverflow.com/questions/13549518/autofac-returns-different-instance-in-asp-net-mvc-web-api">this</a> answer.</p>
  
  <p>EDIT: I believe I may be able to use a <code>System.Net.Http.DelegatingHandler</code> to intercept the WebAPI request which eliminates the need to obtain the <code>HttpRequestMessage</code> during <code>PostAuthenticateRequest</code>. However, that still leaves the question of determining if the request is a web api request or not.</p>