Search code examples
c#asp.net-mvcdependency-injectiononion-architecture

How can I instantiate Services in MVC


I have an ASP.Net MVC 5 project using an Onion Architecture where I have repositories and services and I use Services from my controller. In my controller, I need to use the IGenericService variables I created, but how can I instantiate these variables? The problem being that my Service needs a IRepository for its constructor, and in turn IRepositoryneeds to be initialized too.

What I tried was AddSingleton(IGenericService<MyClass>, GenericService<MyClass>) in the method ConfigureServices(IServiceCollection services) in the Startup.cs file but it doesn't seem to help.

Edit As suggested my @Nkosi I am trying to resolve dependencies and followed this tutorial to do so : http://scottdorman.github.io/2016/03/17/integrating-asp.net-core-dependency-injection-in-mvc-4/ . My problem now is that I get an invalid operation exception :

Unable to resolve service for type 'Repository.PrincipalServerContext' while attempting to activate 'WebExploitv2.Controllers.NavigationController'

My startup.cs looks like this now:

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var services = new ServiceCollection();
        ConfigureAuth(app);
        ConfigureServices(services);
        var resolver = new DefaultDependencyResolver(services.BuildServiceProvider());
        DependencyResolver.SetResolver(resolver);
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllerAsServices(typeof(Startup).Assembly.GetExportedTypes()
            .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
            .Where(t => typeof(IController).IsAssignableFrom(t)
                || t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));

        services.AddSingleton<IGenericRepository<Web_Documents>, GenericRepository<Web_Documents>>();
        services.AddSingleton<IGenericService<Web_Documents>, GenericService<Web_Documents>>();

        services.AddSingleton<IGenericRepository<Web_Categories>, GenericRepository<Web_Categories>>();
        services.AddSingleton<IGenericService<Web_Categories>, GenericService<Web_Categories>>();

        services.AddSingleton<IGenericService<Web_User_joint_Profils>, GenericService<Web_User_joint_Profils>>();
        services.AddSingleton<IGenericRepository<Web_User_joint_Profils>, GenericRepository<Web_User_joint_Profils>>();

        services.AddSingleton<IGenericRepository<Web_Group_joint_Profils>, GenericRepository<Web_Group_joint_Profils>>();
        services.AddSingleton<IGenericService<Web_Group_joint_Profils>, GenericService<Web_Group_joint_Profils>>();


        services.AddSingleton<IMenuService, MenuService>();
        services.AddSingleton<IMenuRepository, MenuRepository>();
    }
}

I also added a DefaultDependencyResolver class :

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

Next I have the ServiceProviderExtension class:

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

Finally in my controller, I have Interfaces of GenericService which allows me to access Repository and in turn access my DB. I use the followed interfaces for instantiation

    private IGenericService<Web_User_joint_Profils> _userProfileService;
    private IGenericService<Web_Group_joint_Profils> _groupProfileService;
    private IGenericService<Web_Categories> _categoryService;
    PrincipalServerContext context;
    private NavigationController(PrincipalServerContext context, IGenericService<Web_User_joint_Profils> userProfileService, IGenericService<Web_Group_joint_Profils> groupProfileService, IGenericService<Web_Categories> categoryService)
    {
        _context = context;
        _userProfileService = userProfileService;
        _groupProfileService = groupProfileService;
        _categoryService = categoryService;
    }

Note that My GenericService takes POCOs as generics in order to know where to look in Database. So for each of these in Startup.ConfigureServices(IServiceCollection services) I added an AddSingleton method to register these services and repositories with the DI container. Any ideas why I get this exception?


Solution

  • It is rather simple, using IServiceCollection instance that is being passed to ConfigureServices method by the run time you do:

    services.AddSingleton<IAbstraction, ConcreteImplementation>();
    

    or, for a transient lifetime scope:

    services.AddTransient<IAbstraction, ConcreteImplementation>();
    

    or, in your case:

    services.AddSingleton<IGenericService<MyClass>, GenericService<MyClass>>();