Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

asp.net adding ApiController as service for dependency injection

Hello I went off this guide to integrate asp.net core Dependency Injection into MVC 5. Originally it worked fine using a default controller (Inherited from System.Web.Mvc.Controller class). But then I wanted the injected dependency to be available in an controller that inherited from System.Web.Http.ApiController. I'm 95% sure the problem is coming from this part of the code where all the controllers are added as services since I'm getting the same error as the guide says I will get without it that portion.

a missing method exception saying that your constructor doesn’t implement the default parameterless constructor

Startup.cs

public static class ServiceProviderExtensions
{
   public static IServiceCollection AddControllersAsServices(this IServiceCollection services,
      IEnumerable<Type> controllerTypes)
   {
      foreach (var type in controllerTypes)
      {
         services.AddTransient(type);
      }

      return services;
   }
}

public partial class Startup
{
  public void ConfigureServices(IServiceCollection services){
    PackageScraperService pScraper = new PackageScraperService();
    services.addSington<IPackageScraper>(pScraper);

    // Problem Code

    services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
     .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
     .Where(t => typeof(IController).IsAssignableFrom(t) 
        || t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));
  }

  public void Configuration(IAppBuilder app){
      var services = new ServiceCollection();

      ConfigureServices(services)
      var resolver = new DefaultDependencyResolver(services.BuildServiceProvider());
      DependencyResolver.SetResolver(resolver);
  }
}

I have looked at the results of

typeof(Startup).Assembly.GetExportedTypes()
     .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
     .Where(t => typeof(IController).IsAssignableFrom(t) 
        || t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase))

and it appears to correctly find my ApiController (ValuesController.cs)

I also changed my api controller to inherit from the Controller class and it worked fine.

Is there a simpler way to add a controller as a service? I've had a incredibly hard time finding documentation for this since I'm using MVC instead of Core.

like image 723
als9xd Avatar asked Aug 05 '18 03:08

als9xd


People also ask

Does ASP NET support dependency injection?

ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies. For more information specific to dependency injection within MVC controllers, see Dependency injection into controllers in ASP.NET Core.

How do you specify the service life for a registered service that is added as a dependency?

Built-in IoC container manages the lifetime of a registered service type. It automatically disposes a service instance based on the specified lifetime. Singleton − IoC container will create and share a single instance of a service throughout the application's lifetime.

What does ApiController attribute do?

The [ApiController] attribute applies inference rules for the default data sources of action parameters. These rules save you from having to identify binding sources manually by applying attributes to the action parameters.

What is ApiController in asp net?

Here, you will learn about Web API Controller in detail. Web API Controller is similar to ASP.NET MVC controller. It handles incoming HTTP requests and send response back to the caller. Web API controller is a class which can be created under the Controllers folder or any other folder under your project's root folder.


1 Answers

Update to include ApiControllers

services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
     .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
     .Where(t => typeof(IController).IsAssignableFrom(t) 
        || typeof(IHttpController).IsAssignableFrom(t));

You will also need to set the dependency resolver for the Web API global configuration.

Update the DefaultDependencyResolver so that it can be used by both MVC and Web API. They share an interface by name but they belong to different namespaces.

public class DefaultDependencyResolver :
    System.Web.Http.Dependencies.IDependencyResolver,
    System.Web.Mvc.IDependencyResolver {

    private readonly IServiceProvider serviceProvider;

    public DefaultDependencyResolver(IServiceProvider serviceProvider) {
        this.serviceProvider = serviceProvider;
    }    

    public object GetService(Type serviceType) {
        return this.serviceProvider.GetService(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType) {
        return this.serviceProvider.GetServices(serviceType);
    }

    //Web API specific

    public System.Web.Http.Dependencies.IDependencyScope BeginScope() {
        return this;
    }

    public void Dispose() {
        // NO-OP, as the container is shared. 
    }
}

And in start up you set the resolver for both MVC and Web API.

public void Configuration(IAppBuilder app){
    var services = new ServiceCollection();    
    ConfigureServices(services);        
    var resolver = new DefaultDependencyResolver(services.BuildServiceProvider());
    DependencyResolver.SetResolver(resolver);//Set MVC
    GlobalConfiguration.Configuration.DependencyResolver = resolver; //Set for Web API
}
like image 99
Nkosi Avatar answered Oct 29 '22 21:10

Nkosi