3

I have an new application that implement onion architecture now i want to inject a service in startup class of owin. The ioc process is launched before hitting the startup class beacuse it's in a bootstrapper project that run first using webactivator. Is it possible to inject a service in startup class ?

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();

        // Web API routes
        config.MapHttpAttributeRoutes();

        ConfigureOAuth(app);

        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

        app.UseWebApi(config);
    }

    public void ConfigureOAuth(IAppBuilder app)
    {
        // i want to use an injected service inside a provider :my problem :(  
        var providers = Providers(service);

        OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            //For Dev enviroment only (on production should be AllowInsecureHttp = false)
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/generateToken"),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
            Provider = providers,
            AccessTokenFormat = new CustomJwtFormat("http://localhost:18292/")
        };

        // OAuth 2.0 Bearer Access Token Generation
        app.UseOAuthAuthorizationServer(OAuthServerOptions);
    }
}
Meirion Hughes
  • 24,994
  • 12
  • 71
  • 122
moyomeh
  • 155
  • 3
  • 14
  • Why don't you pass the provider and/or service to `ConfigureOAuth` method? That is inverting the control. You need an entry where you set up your IOC container, so it may as well be in `StartUp`. Btw, you don't have to follow the `StartUp` convention. You can manually start an owin app if you like. – Meirion Hughes Feb 22 '16 at 14:13
  • thnx for your comment but if i pass the service and/or provider in configureOAuth i should pass it in the Configuration method first because it's the caller.. the problem is that i can't do Configuration(IAppbuilder, service ) beacause it throw an exception ( Startup does not have the expected signature 'void Configuration(IAppBuilder)' .. ) – moyomeh Feb 22 '16 at 14:20
  • yes right you are. I'll show you how I do it. – Meirion Hughes Feb 22 '16 at 14:22

1 Answers1

2

You don't have to use the StartUp convention and in cases like this it might better to have complete control of the app build pipeline. This doesn't directly answer your question, more an extended comment on how you could do it; Specifically, manually setting up an AppBuilder and sending the app to an Owin Server.

btw, I'm using nowin here to make the actual server. I'm sure someone else will answer with the Asp.Net way to do this.

using AppFunc = Func<IDictionary<string, object>, Task>;

public class App
{
    private IAppBuilder _appBuilder;
    private HttpConfiguration _config;
    private ISomeServiceProvider _provider;

    public App(IAppBuilder appBuilder, ISomeServiceProvider provider, HttpConfiguration config)
    {
        _appBuilder = appBuilder;
        _provider = provider;
        _config = config;

        ConfigureOAuth(_appBuilder, provider);

        _appBuilder.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        _appBuilder.UseWebApi(config);

        //Build Owin App
        _owinApp = (AppFunc) _appBuilder.Build(typeof (AppFunc));


    }

    void ConfigureOAuth(IAppBuilder app)
    {
        //...
    }

    public void Start()
    {
        //Make an endpoint
        var owinEndpoint = new System.Net.IPEndPoint(System.Net.IPAddress.Any, 8080);

        //Build WebServer (Nowin)
        var owinServer = ServerBuilder.New()
            .SetOwinApp(_owinApp)
            .SetEndPoint(owinEndpoint)
            .Build();

        // Start WebServer
        using (owinServer)
        {
            owinServer.Start();

            Console.WriteLine("Press ENTER to stop");
            Console.ReadLine();
        }
    }
}

Now somewhere at the bootstrapper / start up stage add the app to the container, resolve it and run it.

public class Program
{
    public static void Main(string[] args)
    {
        var container = GetIoC();

        container.Bind<App>().ToSelf();
        container.Bind<IAppBuilder>().To(()=>new AppBuilder());
        container.Bind<HttpConfiguration>();
        // ... other bindings you need 

        //resolve root
        var app = container.Get<App>();

        app.Start(); 
    }
}

Bear in mind this is pseudo-ish code, but you get the general idea.

Meirion Hughes
  • 24,994
  • 12
  • 71
  • 122
  • It's a good start but i'm wondering if container.Get(); is an anti-pattern. The container in my case is defined in other project so if i will adopt this solution it may be better to use GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IService)) which i'm not sure about it .. – moyomeh Feb 22 '16 at 14:47
  • @mmansouri updated to have a root and have everything injected into an all encompassing `App` – Meirion Hughes Feb 25 '16 at 08:49