0

I've a project using ASPNET MVC5 with WebApi2, OWIN and SimpleInjector as the IoC container.

I've read that if you're using OWIN you should get your HttpConfiguration, you'll create one rather than using GlobalConfiguration.

Like this in StartUp class, Configuration method:

var config = new HttpConfiguration();
config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);

but with that I receive the error that I need a parameterless contructor, and if I use:

GlobalConfiguration.Configuration.DependencyResolver = 
    new SimpleInjectorWebApiDependencyResolver(container);

combined with (in SimpleInjectorInitializer):

container.RegisterWebApiControllers(GlobalConfiguration.Configuration,
    AppDomain.CurrentDomain.GetAssemblies());

It works, but I read on the internet:

A common error in OWIN integration is use of the GlobalConfiguration.Configuration. In OWIN you create the configuration from scratch. You should not reference GlobalConfiguration.Configuration anywhere when using the OWIN integration.

Am I doing it OK for the OWIN and frameworks and technologies being used?

I've tried to follow this implementation of SimpleInjector with WebApi (there they're using MVC so I changed it a little). MVC 5 template (ASP.Net Identity 2.0) combined with Simple Injector

This is my snippet of the StartUp class now:

public partial class Startup
{
public void Configuration(IAppBuilder app)
{
    var container = SimpleInjectorInitializer.Initialize(app);

    GlobalConfiguration.Configuration.DependencyResolver = 
        new SimpleInjectorWebApiDependencyResolver(container);

    ConfigureAuth(app, container);
}

public void ConfigureAuth(IAppBuilder app, Container container)
{
    // Added for IoC usage: See https://simpleinjector.codeplex.com/discussions/564822
    app.Use(async (context, next) => {
        using (container.BeginExecutionContextScope())
        {
            await next();
        }
    });

    app.CreatePerOwinContext(() => container.GetInstance<ApplicationUserManager>());

    // Enable the application to use a cookie to store information for the signed in user
    // and to use a cookie to temporarily store information about a user logging in with a third party login provider
    app.UseCookieAuthentication(new CookieAuthenticationOptions());
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

    // Configure the application for OAuth based flow
    PublicClientId = "self";
    OAuthOptions = new OAuthAuthorizationServerOptions
    {
        TokenEndpointPath = new PathString("/Token"),
        Provider = new ApplicationOAuthProvider(PublicClientId),
        AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
        // In production mode set AllowInsecureHttp = false
        AllowInsecureHttp = true
    };

    // Enable the application to use bearer tokens to authenticate users
    app.UseOAuthBearerTokens(OAuthOptions);
}

SimpleInjectorInitializer class

    public static class SimpleInjectorInitializer
    {
        public static Container Initialize(IAppBuilder app)
        {
            var container = GetInitializeContainer(app);

            container.Verify();

            return container;
        }

        public static Container GetInitializeContainer(IAppBuilder app)
        {
            var container = new SimpleInjector.Container();

            container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();

            container.RegisterSingleton<IAppBuilder>(app);

            #region Webapi Registration

            // IoC for ASP.NET Identity
            container.RegisterWebApiRequest<ApplicationUserManager>();
            container.RegisterWebApiRequest<ApplicationDbContext>(() => new ApplicationDbContext(ConfigurationManager.ConnectionStrings["orgIdentityConnectionString"].ConnectionString));
            container.RegisterWebApiRequest<IUserStore<ApplicationUser>>(() => new UserStore<ApplicationUser>(container.GetInstance<ApplicationDbContext>()));
            container.RegisterInitializer<ApplicationUserManager>(manager => InitializeUserManager(manager, app));

            // Setup for ISecureDataFormat
            container.RegisterWebApiRequest<ISecureDataFormat<AuthenticationTicket>, SecureDataFormat<AuthenticationTicket>>();
            container.RegisterWebApiRequest<ITextEncoder, Base64UrlTextEncoder>();
            container.RegisterWebApiRequest<IDataSerializer<AuthenticationTicket>, TicketSerializer>();
            container.RegisterWebApiRequest<IDataProtector>(() => new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider().Create("ASP.NET Identity"));

            #endregion

            container.RegisterWebApiRequest<IAuthenticationManager>(() =>
                AdvancedExtensions.IsVerifying(container)
                ? new OwinContext(new Dictionary<string, object>()).Authentication
                : HttpContext.Current.GetOwinContext().Authentication);

            // The initialization runs all the map creation once so it is then done when you come to do your mapping. 
            // You can create a map whenever you want, but this will slow your code down as the mapping creation involves reflection.
            Mapper.Initialize(config =>
            {
                config.ConstructServicesUsing(container.GetInstance);
                config.AddProfile(new WebApiAutomapperProfile());
                config.AddGlobalIgnore("Errors");
                config.AddGlobalIgnore("IsModelValid");
                config.AddGlobalIgnore("BaseValidator");
                config.AddGlobalIgnore("AuditInformation");
            });

            var profiles = Assembly.GetExecutingAssembly()
                        .GetTypes()
                        .Where(x => typeof(AutoMapper.Profile).IsAssignableFrom(x));

            var config2 = new MapperConfiguration(cfg =>
            {
                foreach (var profile in profiles)
                {
                    cfg.AddProfile(Activator.CreateInstance(profile) as AutoMapper.Profile);
                }
            });

            container.RegisterSingleton<MapperConfiguration>(config2);
            container.Register<IMapper>(() => config2.CreateMapper(container.GetInstance));

            #region MyStuff Registrations

            container.Register(typeof(IRepository<>), typeof(orgRepository<>), Lifestyle.Scoped);
            container.Register(typeof(IDatabaseFactory<>), typeof(DatabaseFactory<>), Lifestyle.Scoped);

            var orgCatalogRegistration = Lifestyle.Scoped.CreateRegistration<Catalog>(container);
            container.AddRegistration(typeof(IPublicCatalog), orgCatalogRegistration);
            container.AddRegistration(typeof(IPrivateCatalog), orgCatalogRegistration);

            #endregion

**// TODO: A common error in OWIN integration is use of the GlobalConfiguration.Configuration. In OWIN you create the configuration from scratch. You should not reference GlobalConfiguration.Configuration anywhere when using the OWIN integration.**

//Is the following line OK?

    container.RegisterWebApiControllers(GlobalConfiguration.Configuration, AppDomain.CurrentDomain.GetAssemblies());

            return container;
        }

        private static void InitializeUserManager(ApplicationUserManager manager, IAppBuilder app)
        {
            manager.UserValidator = new UserValidator<ApplicationUser>(manager)
            {
                AllowOnlyAlphanumericUserNames = false,
                RequireUniqueEmail = true
            };

            //Configure validation logic for passwords
            manager.PasswordValidator = new PasswordValidator()
            {
                RequiredLength = 6,
                RequireNonLetterOrDigit = false,
                RequireDigit = true,
                RequireLowercase = true,
                RequireUppercase = true,
            };

            var dataProtectionProvider =
                 app.GetDataProtectionProvider();

            if (dataProtectionProvider != null)
            {
                manager.UserTokenProvider =
                 new DataProtectorTokenProvider<ApplicationUser>(
                  dataProtectionProvider.Create("ASP.NET Identity"));
            }
        }
    }
}
Steven
  • 166,672
  • 24
  • 332
  • 435
polonskyg
  • 4,269
  • 9
  • 41
  • 93
  • "but I read in the internet". Do you have a reference to that source? – Steven Sep 02 '16 at 07:10
  • Seems to me that your question isn't really Simple Injector specific. You might want to reflect that to attract the right crowd. Although I have quite some experience with Simple Injector, I can't answer your question. – Steven Sep 02 '16 at 07:12
  • @steven, the comment was taken from another StackOverflow post, here is the link: http://stackoverflow.com/questions/25177734/dependency-injection-not-working-with-owin-self-hosted-web-api-2-and-autofac It's using Autofac but the principle applies the same. – polonskyg Sep 02 '16 at 12:44

1 Answers1

0

If you take a look at the same page you got that quote from, you'll see you have to register the Web API configuration into OWIN's IAppBuilder as follows:

app.UseWebApi(config);
Steven
  • 166,672
  • 24
  • 332
  • 435
  • That's a different approach or at least not the one that comes with the WebApi tamplate in MVC5 but creating an OWIN-Katana project from Scratch. Despite I'm thinking on doing that, the question stil remains on how to configure SimpleInjector for those two things at the top of the question using GlobalConfiguration.Configuration – polonskyg Sep 02 '16 at 12:46
  • I have no idea why ising the global config is a bad idea. If that works, i would say go for it. – Steven Sep 02 '16 at 13:06
  • I asked on the Autofac forum why the Autofac docs state that using the GlobalConfiguration is a bad idea. [Here is Tillig's answer](https://github.com/autofac/Autofac.WebApi.Owin/issues/5). The basic problem with GlobalConfiguration is that it is easy to get wrong, because people tend to mix it up with manual cconfiguration creation, but when done right, there is no behavioral difference. It's up to you what path to walk. – Steven Sep 02 '16 at 16:44
  • Thx, I see now that using it correctly is not a problem. I'll mark your answer as correct due to the comment that made me acknowledge it's not an error its usage. – polonskyg Sep 02 '16 at 20:58