r3plica
r3plica

Reputation: 13387

Autofac Web API 2 and Owin resolve in StartupConfig

I have a project that is both OWIN and Web API 2. I have tried to follow the instructions as best as I can. Inside my Configration method in the StartupConfig class I have this:

// Get our configuration
var config = new HttpConfiguration();
var container = ConfigureInversionOfControl(app, config);
var scope = config.DependencyResolver.GetRequestLifetimeScope();
var serverOptions = ConfigureOAuthTokenGeneration(app, scope);

//** removed for brevity **//

// Cors must be first, or it will not work
app.UseCors(CorsOptions.AllowAll);

// Register the Autofac middleware FIRST. This also adds
// Autofac-injected middleware registered with the container.
app.UseAutofacMiddleware(container);
//app.UseAutofacWebApi(config);
app.UseOAuthAuthorizationServer(serverOptions);
app.UseWebApi(config);

My ConfigurInversionOfControl method looks like this:

private static IContainer ConfigureInversionOfControl(IAppBuilder app, HttpConfiguration config)
{

    // Create our container
    var builder = new ContainerBuilder();

    // You can register controllers all at once using assembly scanning...
    builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

    // Add our dependencies (Can't use life because this is available to all controllers http://stackoverflow.com/questions/36173210/get-same-instance-of-a-component-registered-with-autofac-as-instanceperlifetimes)
    builder.RegisterType<UnitOfWork<DatabaseContext>>().As<IUnitOfWork>().InstancePerRequest();

    // Register our services
    builder.Register(c => new AdvancedEncryptionStandardProvider(ConfigurationManager.AppSettings["rm:key"], ConfigurationManager.AppSettings["rm:secret"])).As<IAdvancedEncryptionStandardProvider>();
    builder.RegisterType<LogService>().As<ILogService>();
    builder.RegisterType<EmailService>().As<IEmailService>();
    builder.RegisterType<RefreshTokenService>().As<IRefreshTokenService>();

    // Register our providers
    builder.Register(c => new SendGridProvider(c.Resolve<IUnitOfWork>(), c.Resolve<IEmailService>(), ConfigurationManager.AppSettings["SendGridApiKey"])).As<ISendGridProvider>();
    builder.RegisterType<LogProvider>().As<ILogProvider>();
    builder.RegisterType<RefreshTokenProvider>().As<IAuthenticationTokenProvider>();
    builder.RegisterType<OAuthProvider>().As<OAuthProvider>();

    // Build
    var container = builder.Build();

    // Lets Web API know it should locate services using the AutofacWebApiDependencyResolver
    config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

    // Return our container
    return container;
}

Now I have set this up (I assume correctly). How do I resolve one of the services in my StartupConfig class? I need to be able to create an instance of the OAuthProvider and RefreshTokenProvider. I tried something similar to this:

// Get our providers
var authProvider = scope.Resolve<OAuthProvider>();
var refreshTokenProvider = scope.Resolve<IAuthenticationTokenProvider>();

// Create our OAuth options
return new OAuthAuthorizationServerOptions()
{
    AllowInsecureHttp = true, // TODO: Remove this line
    TokenEndpointPath = new PathString("/oauth/access_token"),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
    AccessTokenFormat = new Business.Authentication.JwtFormat("http://localhost:62668"),
    Provider = authProvider,
    RefreshTokenProvider = refreshTokenProvider
};

But when it reaches the line var authProvider = scope.Resolve<OAuthProvider>();, I get an error stating:

Parameter cannot be null: Parameter name: context

Now I would assume that the context has not been created yet, so I assume I am doing something wrong with my resolve. Can anyone help?

Upvotes: 2

Views: 570

Answers (1)

r3plica
r3plica

Reputation: 13387

This was actually really simple. I needed the change the scope from:

var scope = config.DependencyResolver.GetRequestLifetimeScope();

to

var scope = config.DependencyResolver.GetRootLifetimeScope();

I assume because the "request" is not available in the StartupConfig class. Anyway, changing this fixed my issue.

Upvotes: 1

Related Questions