Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple Injector initialize for both MVC and Web API controllers

I have a Web API controller that has some resources DI'd. Out of later necessity I have added an MVC controller, now I need same resources DI'd there as well. Here is my original configuration:

    [assembly: WebActivator.PostApplicationStartMethod(typeof(CineplexSearch.App_Start.SimpleInjectorWebApiInitializer), "Initialize")]

namespace CineplexSearch.App_Start
{
    using System.Web.Http;
    using SimpleInjector;
    using SimpleInjector.Integration.WebApi;

    public static class SimpleInjectorWebApiInitializer
    {
        /// <summary>Initialize the container and register it as Web API Dependency Resolver.</summary>
        public static void Initialize()
        {
            var container = new Container();
            container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();

            InitializeContainer(container);

            container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

            container.Verify();

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

        private static void InitializeContainer(Container container)
        {
            container.Register<ICachingManager, CachingManager>(Lifestyle.Transient);
            container.Register<IDataAccessLayer, DataAccessLayer>(Lifestyle.Transient);
        }
    }
}

Can I register DI for MVC Controller in the same place as well? Can I reuse the container?

Update: I must be close, but now I get an error in the Web API controller that I need a parameterless constructor; I tried adding it, but then nothing gets injected of course

public static class SimpleInjectorWebApiInitializer
{
    /// <summary>Initialize the container and register it as Web API Dependency Resolver.</summary>
    public static void Initialize()
    {
        var container = new Container();
        container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

        InitializeContainer(container);

        container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
        container.RegisterMvcControllers(Assembly.GetExecutingAssembly());

        container.Verify();

        //GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
        DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
    }

    private static void InitializeContainer(Container container)
    {
        container.Register<ICachingManager, CachingManager>(Lifestyle.Transient);
        container.Register<IDataAccessLayer, DataAccessLayer>(Lifestyle.Transient);
    }
}
like image 758
FailedUnitTest Avatar asked May 31 '16 14:05

FailedUnitTest


People also ask

Can I use MVC controller as Web API?

In order to add a Web API Controller you will need to Right Click the Controllers folder in the Solution Explorer and click on Add and then Controller. Now from the Add Scaffold window, choose the Web API 2 Controller – Empty option as shown below. Then give it a suitable name and click OK.

How can we inject the service dependency into the controller?

ASP.NET Core injects objects of dependency classes through constructor or method by using built-in IoC container. The built-in container is represented by IServiceProvider implementation that supports constructor injection by default.

Can I add API controller to MVC project?

If you have MVC project and you need to add Web API controller to this project, it can be done very easy. 1. Add Nuget package Microsoft. AspNet.


3 Answers

Can I reuse the container?

Yes you can, and you should. Every app domain should typically have one container instance.

The MVC integration documentation of the Simple Injector documentation explains that you should set the MVC DependencyResolver as follows:

DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

To make things easier however, your should register the WebRequestLifestyle as DefaultScopedLifestyle:

container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

This will work for Web API as well, since you are solely running Web API from within IIS.

So you need to configure both the DependencyResolvers.

like image 166
Steven Avatar answered Nov 09 '22 09:11

Steven


I would like to add my two cents because after reading Steven's answer and the comments below it I still got some errors. Eventually this had to do with the order in which things are getting configured.

protected void Application_Start()
{
    //set the default scoped lifestyle
    Container container = new Container();
    container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

    ...
    //do class registration here. I did it with Scoped lifestyle
    ...
    //Let the SimpleInjector.Intergration packages register the controllers.       
    container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
    container.RegisterMvcControllers(Assembly.GetExecutingAssembly());

    AreaRegistration.RegisterAllAreas();
    //This must be here because we first need to do above before registering the web api. See WebApiConfig code.
    GlobalConfiguration.Configure(WebApiConfig.Register);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    //don't set the resolver here, do it in WebApiConfig.Register()
    //DependencyResolver.SetResolver(new SimpleInjectorWebApiDependencyResolver(container));
    DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
    container.Verify(SimpleInjector.VerificationOption.VerifyAndDiagnose);
}

WebApiConfig:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();
        //set the webApi resolver here!
        config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(DependencyInjectionCoreSetup._Container);
        //then the rest..
        var route = config.Routes.MapHttpRoute(
        ....
    }
}
like image 24
CularBytes Avatar answered Nov 09 '22 10:11

CularBytes


Also be aware that the WebRequestLifestyle() is obsolete at the time . You can use instead:

//...

container.Options.DefaultScopedLifestyle = new SimpleInjector.Lifestyles.AsyncScopedLifestyle();

//...
like image 1
Bruno Mósca Avatar answered Nov 09 '22 09:11

Bruno Mósca