title: Get reference to requested Controller and Action in custom middleware in ASP.NET Core
body: <p>I'm developing a custom middleware for authenticating clients that invokes an API.</p>
  
  <p>I use an attribute to define if an Action requires authentication, but I can't figure out how to get a reference to the requested <em>Controller</em> and <em>Action</em> inside the Invoke method.</p>
  
  <p>Below is my code so far</p>
  
  <p><strong>AuthenticateClient.cs</strong>:</p>
  
  <pre><code>public class AuthenticateClient
  {
      private readonly RequestDelegate _next;
      private readonly ILogger _logger;
      private readonly GenericUnitOfWork _worker;
  
      public AuthenticateClient(RequestDelegate next, ApiDbContext db, IHttpContextAccessor httpContext, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptions&lt;Utility.LCLog.Settings&gt; settings)
      {
          _next = next;
          _logger = loggerFactory.CreateLogger(settings.Value.ApplicationName);
          _worker = new GenericUnitOfWork(new AppHelper(httpContext, db, env));
      }
  
      public async Task Invoke(HttpContext context)
      {
          if (!context.Request.Headers.Keys.Contains("ClientAuth"))
          {
              _logger.LogWarning("ClientAuth missing in request", new string[] { "Host: " + context.Request.Host, "IP: " + context.Request.HttpContext.Connection.RemoteIpAddress });
  
              context.Response.StatusCode = 400;
              await context.Response.WriteAsync("ClientAuth missing from request header values");
  
              return;
          }
          else
          {
              string[] tmp = context.Request.Headers["ClientAuth"].ToString().Split("/");
  
              if (tmp.Length != 2)
              {
                  context.Response.StatusCode = 400;
                  await context.Response.WriteAsync("The format of the ClientAuth value is wrong");
  
                  return;
              }
              else
              {
                  Client client;
                  string key, pass;
  
                  key = tmp[0];
                  pass = tmp[1];
  
                  client = await _worker.GetRepo&lt;Client&gt;().SingleOrDefault(clnt =&gt; clnt.Active &amp;&amp; clnt.Key.Equals(key) &amp;&amp; clnt.Password.Equals(pass));
  
                  if (client == null)
                  {
                      _logger.LogWarning("Client authentication failed", new string[] { "Key: " + key, "Password: " + pass, "Host: " + context.Request.Host, "IP: " + context.Request.HttpContext.Connection.RemoteIpAddress });
  
                      context.Response.StatusCode = 401;
                      await context.Response.WriteAsync("Authentication failed");
  
                      return;
                  }
              }                
          }
  
          await _next.Invoke(context);
      }
  }
  </code></pre>
  
  <p><strong>ClientAuthenticationAttribute.cs</strong>:</p>
  
  <pre><code>[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
  public class ClientAuthenticationAttribute : Attribute
  {
      private readonly bool _authRequired;
  
      public ClientAuthenticationAttribute(bool authRequired = true)
      {
          _authRequired = authRequired;
      }
  
      public bool AuthRequired { get { return _authRequired; } }
  }
  </code></pre>