简体   繁体   中英

How do I inject dependency in webapi in .net framework using Microsoft.Extensions.DependencyInjection?

I am trying to inject my logger as dependency in a.Net Framework 4.7.2 web api project by following these instructions:

https://scottdorman.blog/2016/03/17/integrating-asp-net-core-dependency-injection-in-mvc-4/

This works great for MVC web application but fails on the webapi project with the "parameterless constructor missing" error.

How do I successfully inject using just the default assembly: Microsoft.Extensions.DependencyInjection in framework?

public class Startup
{
    public void Configuration(IAppBuilder app)
    {

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

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
            .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
            .Where(t => typeof(IController).IsAssignableFrom(t)
                        || t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));
        services.AddSingleton<IMyInterface , MyClass>();
    }
}
public class DefaultDependencyResolver : IDependencyResolver
{
    protected 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);
    }
}

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

        return services;
    }
}

Getting "Parameterless constructor is missing" error with an injection like this:

private IMyInterface _my;
public HomeController(IMyInterface my)
{
    _my= my;
}

Registration Explanation

One issue is that you are registering your DependencyResolver with the MVC resolver registration API which unfortunately is different from the WebAPI resolver registration API. What you want to do instead is:

public void Configuration(IAppBuilder app)
{    
    var services = new ServiceCollection();
    ConfigureServices(services);
    var resolver = new DefaultDependencyResolver(services.BuildServiceProvider());
    HttpConfiguration config = new HttpConfiguration();
    config.DependencyResolver = resolver;
    app.UseWebApi(config);
}

Also note that the IDependencyResolver interface is defined separately in System.Web.Http , so your DefaultDependencyResolver class needs to be updated to derive from it instead.

One thing that has changed on that interface is that there is a BeginScope API. To implement that, call the CreateScope Extension Method exposed on IServiceProvider in Microsoft.Extensions.DependencyInjection to get a new scope. Then pass the provider from that scope to a new instance of your DefaultDependencyResolver.

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

Full Example

The blog example you were following for MVC was using OWIN. When I set out to make a full example, I hit the same error as you, and it was because I hadn't correctly configured OWIN so Startup was never being called. Here is a full working example of Microsoft.Extensions.DependencyInjection being used to inject into both MVC and WebAPI Controllers:

https://github.com/ryandle/MVC_WebApi_DI_Example

Are you using [Serializable] on your HomeController? If so, when using it you need a constructor without parameters.

Try add this: public HomeController() { } and run again.

More info: parameter less constructor error

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM