1

I need to configure Autofac DI container in ASP.NET CORE 3.1 Web API application and call register class from the container in Web API controller. I install Autofac.Extensions.DependencyInjection (6.0.0) and try to register container in my Startup.cs class but I am not able to use service. Also, do I need to configure the container in ConfigureServices(IServiceCollection services) class? The debugger does not hit IoCConfigurator() class after hitting point builder.RegisterModule(new IoCConfigurator());

Program.cs

 public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseServiceProviderFactory(new AutofacServiceProviderFactory())
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Startup.cs

 public class Startup
{
    public IConfiguration Configuration { get; }
    public ContainerBuilder containerBuilder { get; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
        containerBuilder = new ContainerBuilder();
    }

    public void ConfigureServices(IServiceCollection services)
    {
        ServicesConfigurator.Configure(services, Configuration);
        ConfigureIoC(services, containerBuilder);
    }

    public void ConfigureIoC(IServiceCollection services, ContainerBuilder builder)
    {

        builder.RegisterModule(new IoCConfigurator());
    }

IoCConfigurator.cs

 public class IoCConfigurator: Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<NotifyService>().As<INotificationService>();
        builder.RegisterType<UsersService>().AsSelf();
    }
 }

INotification Interface & Class

 public interface INotificationService
{
   void notifyUsernameChanged(Users users);
}

   public class NotifyService : INotificationService
{
    public void notifyUsernameChanged(Users users)
    {
        string changedUsername = users.Username;

        Console.WriteLine("Username has changed to ... ");
        Console.WriteLine(changedUsername);
    }
}

User & User Service Class

 public class Users
{
    public string Username { get; set; }

    public Users(string username)
    {
        this.Username = username;
    }  
}

public class UsersService
{
    private INotificationService _notificationService;
    public UsersService(INotificationService notificationService)
    {
        this._notificationService = notificationService;
    }

    public void ChangeUsername(Users users, string newUsername)
    {
        users.Username = newUsername;
        _notificationService.notifyUsernameChanged(users);
    }
}

API Controller where I want to class the UserService Class and get reference from DI container

[Authorize]
[Route("txn/v1/[controller]/[action]")]
[ApiController]
public class DashboardController : ControllerBase
{

  [HttpPost("{name}")]
    public ActionResult<HelloMessage> GetMessage(string name)
    {
        // call container here...
        var result = new HelloMessage()
        {
            GivenName = name,
            ReturnMessage = "Dashboard@ Hello, Welcome to Texanite Digital"
        };

        return result;
    }
K.Z
  • 5,201
  • 25
  • 104
  • 240
  • Have you checked the [documentation](https://autofaccn.readthedocs.io/en/latest/integration/aspnetcore.html#asp-net-core-3-0-and-generic-hosting)? – Mat J Jul 21 '20 at 17:48

2 Answers2

3

Here is how I set it up. From command line:

md autof
cd autof
dotnet new webapi
dotnet add package Autofac.Extensions.DependencyInjection

Then edit using VS or VSCode. Program.cs - as you had it:

public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseServiceProviderFactory(new AutofacServiceProviderFactory())
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });

Next in Startup.cs, forget about ConfigureIoC, just register the services you want/need:

public void ConfigureContainer(ContainerBuilder builder)
    {
        // Register your own things directly with Autofac, like:
        //builder.RegisterModule();
        builder.RegisterType<NotifyService>().As<INotificationService>();
    }

Then in DashboardController.cs you need to "inject" the needed services from the constructor:

public class HelloMessage {
    public string GivenName { get; set; }
    public string ReturnMessage { get; set; }
}

//[Authorize]   Easier without Auth - don't need
[Route("[controller]")]
[ApiController]
public class DashboardController : ControllerBase
{
    private readonly INotificationService _notifyService;

    public DashboardController(INotificationService notifyService)
    {
        _notifyService = notifyService;
    }

    //[HttpPost("{name}")] - easier to test Get
    [HttpGet("{name}")]
    public ActionResult<HelloMessage> GetMessage(string name)
    {
        // call container here...
        _notifyService.notifyUsernameChanged(new Users(name));

        var result = new HelloMessage()
        {
            GivenName = name,
            ReturnMessage = $"Dashboard {name}, Welcome to Texanite Digital"
        };

        return result;
    }
}

My Results: Browser snip

With console output: console output with toxic name Your UserService was a little "out of the loop" but you can add an Interface for it and register with container and add it to injected services of the controller(s).

I could zip the whole thing up, just don't know where to put it or send it...

Jester
  • 2,728
  • 22
  • 20
  • I have managed to run all code... thanks for guiding me on this. one thing I don't understand; as register all the interfaces and classes in the autofac container then why need to refer namespace of required classes in the controller to use it and not using the container to resolve it. futher, how can I access the singleton container reference in a class so that I use that in all the controllers ? – K.Z Jul 24 '20 at 09:48
0

Change your code like, that is all I think

Program.cs

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .UseServiceProviderFactory(new AutofacServiceProviderFactory())
        .ConfigureContainer<ContainerBuilder>(builder =>
        {
            builder.RegisterModule(new IoCConfigurator());
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });
}

Startup.cs

public class Startup
{
public IConfiguration Configuration { get; }
public ContainerBuilder containerBuilder { get; }

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
    containerBuilder = new ContainerBuilder();
}

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
}
ZootHii
  • 800
  • 1
  • 8
  • 16