Skip to content

Instantly share code, notes, and snippets.

@tugberkugurlu
Last active August 29, 2015 13:56
Show Gist options
  • Save tugberkugurlu/9054704 to your computer and use it in GitHub Desktop.
Save tugberkugurlu/9054704 to your computer and use it in GitHub Desktop.

I have an IFoo instance which I need to use as per request instance. Here is how my startup class look like:

public void Configuration(IAppBuilder app)
{
    HttpConfiguration config = new HttpConfiguration();
    config.Routes.MapHttpRoute("DefaultHttpRoute", "api/{controller}");

    app.Use<RandomTextMiddleware>()
       .UseWebApi(config);
}

RandomTextMiddleware is a pass-through middleware and I need an instance of IFoo implementation there. I also need an instance of IFoo implementation inside my Web API pipeline.

How would you solve this problem so that I have the same instance of IFoo implementation inside the RandomTextMiddleware and the Web API pipeline per HTTP request?

@beyond-code-github
Copy link

If we keep OWIN clean in this way, then I believe there is a need for an 'interoperable pipeline' that can provide the ability for adding middleware-like components that work within the context of an app, but independantly of framework. This is something that Superscribe aims to provide.

@tugberkugurlu
Copy link
Author

@panesofglass

I don't know how you could expect a middleware to use a specific mechanism or instance and be re-usable.

Here is an example: OAuthAuthorizationServerMiddleware (UseOAuthAuthorizationServer).

ILogger logger = app.CreateLogger<MyOAuthAuthorizationServerProvider>();
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions 
{
    TokenEndpointPath = new PathString("/token"),
    AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(10),
    Provider = new MyOAuthAuthorizationServerProvider(logger)
});

Here is my provider:

public class MyOAuthAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    private const string ClientContextKey = "my:oauth:client";
    private readonly ILogger _logger;

    public MyOAuthAuthorizationServerProvider(ILogger logger)
    {
        _logger = logger;
    }

    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        string clientId;
        string clientSecret;

        if (context.TryGetBasicCredentials(out clientId, out clientSecret))
        {
            IServiceProvider requestContainer = context.OwinContext.Environment.GetRequestContainer();
            IClientManager clientManager = requestContainer.GetService<IClientManager>();
            Client client = await clientManager.GetVerfiedClientAsync(clientId, clientSecret);

            if (client != null)
            {
                context.OwinContext.Set<Client>(ClientContextKey, client);
                context.Validated(clientId);
                return;
            }
        }

        context.Rejected();
    }

    // ...
}

Noticed requestContainer.GetService<IClientManager>()? OAuthAuthorizationServerMiddleware is still reusable and I'm able to use my DI implementation on top of OWIN environment, w/o any coupling at all.

@tugberkugurlu
Copy link
Author

@panesofglass

Also, I don't know of a library/framework agnostic dependency injection mechanism. So if you use Autofac in your middleware but I use StructureMap in my app that uses your middleware, then I have yet another dependency issue. Your middleware just created another problem for my app.

Again, you won't be tied to a specific IoC container, we will just bound to IServiceProvider. Please review the following readme file and the source code: https://github.com/DotNetDoodle/DotNetDoodle.Owin.Dependencies#readme

I guess there is a misunderstanding between what I wanted to do and what I expressed.

@darrelmiller
Copy link

The HTTP request has a much longer lifetime than the time it spends in your Owin pipeline. The HTTP Request is created by the client, it passes through the local client proxy cache, it goes through corporate proxies, through your ISPs public caching infrastructure, through your reverse proxy. Owin middleware is just another intermediary in that huge pipeline that extends from client to origin server. It just happens to run in the same process as your application. The fact that you can share state between owin middleware doesn't mean you should.

Maybe tomorrow, you will need to load balance your application servers and it makes more sense to run that piece of middleware on the reverse proxy rather than running an instance on each app server. If you have coupling between your middleware, that is going to make it harder to move.

@darrelmiller
Copy link

Why not just inject IClientManager into the MyOAuthAuthorizationServerProvider constructor at application startup time?

@tugberkugurlu
Copy link
Author

Why not just inject IClientManager into the MyOAuthAuthorizationServerProvider constructor at application startup time?

Simple, it's not thread safe. It should be constructed per each request.

@tugberkugurlu
Copy link
Author

@yreynhout
Copy link

Factory, anyone?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment