3

I want to know if is it possible to send value from middleware to controllerAPI ?

For example, I want catch one particular header and send to the controller.

Something like that :

 public class UserTokenValidatorsMiddleware
{
    private readonly RequestDelegate _next;
    //private IContactsRepository ContactsRepo { get; set; }

    public UserTokenValidatorsMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        if (!context.Request.Path.Value.Contains("auth"))
        {
            if (!context.Request.Headers.Keys.Contains("user-token"))
            {
                context.Response.StatusCode = 400; //Bad Request                
                await context.Response.WriteAsync("User token is missing");
                return;
            }
            // Here I want send the header to all controller asked. 
        }

        await _next.Invoke(context);
    }
}

#region ExtensionMethod
public static class UserTokenValidatorsExtension
{
    public static IApplicationBuilder ApplyUserTokenValidation(this IApplicationBuilder app)
    {
        app.UseMiddleware<UserTokenValidatorsMiddleware>();
        return app;
    }
}
#endregion 
Ralf Bönning
  • 14,515
  • 5
  • 49
  • 67
Yvan
  • 1,081
  • 2
  • 20
  • 27

1 Answers1

4

What I did was making use of these things:

  • Dependency Injection (Unity)
  • ActionFilterAttribute (because I have access to the IDependencyResolver)
  • HierarchicalLifetimeManager(so I get a new instance per request)(Read about dependency scope)

Action filter

    public class TokenFetcherAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            var token = actionContext.Request.Headers.Authorization.Parameter;
            var scheme = actionContext.Request.Headers.Authorization.Scheme;

            if (token == null || scheme != "Bearer")
                return;

            var tokenProvider = (TokenProvider) actionContext.Request.GetDependencyScope().GetService(typeof(TokenProvider));
            tokenProvider.SetToken(token);
        }
    }

TokenProvider

    public class TokenProvider
    {
        public string Token { get; private set; }

        public void SetToken(string token)
        {
            if(Token != null)
                throw new InvalidOperationException("Token is already set in this session.");

            Token = token;
        }
    }

Unity configuration

container.RegisterType<TokenProvider>(new HierarchicalLifetimeManager()); // Gets a new TokenProvider per request

Controller

[TokenFetcher]
public class SomeController : ApiController
{
    private TokenProvider tokenProvider;

    // The token will not be set when ctor is called, but will be set before method is called.
    private string Token => tokenProvider.Token;

    public SomeController(TokenProvider provider)
    {
        tokeProvider = provider;
    }

    public string Get()
    {
         return $"Token is {Token}";
    }
}

UPDATE

For asp.net core use the builtin DI container. Register the TokenProvider as Transient to get a new one per request:

services.AddTransient<TokenProvider>();
Michael
  • 3,350
  • 2
  • 21
  • 35
  • Sorry, was not paying attention to the fact that it was asp.net core. See my updated answer to see if this will work. Not sure how Actions works and how you get the `TokenProvider`out of service container. But try to use intellisense to figure that out. – Michael Aug 19 '16 at 13:49