11

I am trying to implement Asp.Net webApi project which is depending on a third-party framework that does a lot of stuff with HttpContext.Current which does not exists in Asp.net Core. That is why I could not create Asp.net Core Web Application targeting .net full framework.

So I created old-school Asp.net Web Application project with WebApi extension.

Now I am trying to use Microsoft.Extension.DependencyInjection framework with it.

I found this example for Asp.Net Mvc4 but my project is WebApi. That approach did not work. Can anyone provide link or code snippet for me to move forward?

P.S: When providing an example, please make sure it should not use OWIN framework. Because when I tried to use OWIN pipeline, the third-party library(closed source) is not working properly.

Luke Girvin
  • 13,221
  • 9
  • 64
  • 84
telli
  • 363
  • 3
  • 14

1 Answers1

28

I also found that example a while ago, i make it work perfect both in Asp.Net Mvc4 and WebApi2 project.

Use some IoC container (eg. Unity, Autofac) for WebApi project, the most important thing is implementing the interface IDependencyResolver to make your own dependency resolver.

Hers's my code snippet for WebApi project.

WebApiConfig

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        ...

        // using Microsoft.Extension.DependencyInjection here.
        Startup.Bootstrapper(config);
    }
}

Startup

public class Startup
{
    public static void Bootstrapper(HttpConfiguration config)
    {
        var provider = Configuration();
        var resolver = new DefaultDependencyResolver(provider);

        config.DependencyResolver = resolver;
    }

    private static IServiceProvider Configuration()
    {
        var services = new ServiceCollection();

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

        var serviceProvider = services.BuildServiceProvider();

        return serviceProvider;
    }
}

DefaultDependencyResolver

public class DefaultDependencyResolver : IDependencyResolver
{
    private IServiceScope serviceScope;
    protected IServiceProvider ServiceProvider { get; set; }

    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);
    }

    public IDependencyScope BeginScope()
    {
        serviceScope = this.ServiceProvider.CreateScope();
        return new DefaultDependencyResolver(serviceScope.ServiceProvider);
    }

    public void Dispose()
    {
        // you can implement this interface just when you use .net core 2.0
        // this.ServiceProvider.Dispose();

        //need to dispose the scope otherwise
        //you'll get a memory leak
        serviceScope?.Dispose();
    }
}

ServiceProviderExtensions

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

        return services;
    }
}
spottedmahn
  • 14,823
  • 13
  • 108
  • 178
Hin Liang
  • 296
  • 3
  • 5
  • 1
    Thanks for the solution. I was a bit late to confirm it. – telli Jun 11 '18 at 08:27
  • This was great and worked, but one small suggestion: it's not clear that any instance/type that you want to inject into your controller's constructor, *also* needs to be added to the services collection. From my limited testing, it appears the resolver needs both the "injectibles", and "injectees" added as services. – Don Rhummy Apr 08 '19 at 18:36
  • Excellent answer @Hin Liang – Francois Aug 23 '19 at 11:16
  • In .net 4.x with both mvc and web api in the same app, setting just HttpConfiguration.DependencyResolver only worked for web api for me, for mvc I had to also set the System.Web.Mvc.DependencyResolver which uses System.Web.Mvc.IDependencyResolver which is different to System.Web.Http.Dependencies.IDependencyResolver. Refer to: https://stackoverflow.com/questions/15494920/ – Steven Quick Jun 29 '21 at 05:40
  • How does this handle per-request scoping? – Sedat Kapanoglu Apr 01 '22 at 04:14