dapper with autofac and repository pattern

asp.net-web-api autofac dapper

Question

I am using dapper with the repository pattern in a WebApi Application and I have the following problem. The Repository Class is as follows

  public class Repository : DataConnection, IRepository
  {

    public Repository(IDbConnection connection)
        : base(connection)
    {

    }

    public T GetFirst<T>(object filters) where T : new()
    {
        //Creates the sql generator
        var sqlGenerator = new MicroOrm.Pocos.SqlGenerator.SqlGenerator<T>();

        //Creates the query 
        var query = sqlGenerator.GetSelect(filters);

        //Execute the query
        return Connection.Query<T>(query, filters).FirstOrDefault();
    }

The IRepository Interface has only one method, the GetFirst. A Controller that uses this repository is as follows

public class UsersController : ApiController
{
    private IRepository Repository;

    public UsersController(IRepository repository)
    {
        Repository = repository;
    }

    public User Get(int id)
    {
        return Repository.GetFirst<User>(new { id });
    }
}

I use autofac as DI and in the Application_Start method in Global.asax I use the following code

string connString =  ConfigurationManager.ConnectionStrings["DapperDemo"].ConnectionString;
        SqlConnection connnection = new SqlConnection(connString);
        var builder = new ContainerBuilder();
        builder.RegisterType<Repository>().As<IRepository>();
        builder.RegisterType<UsersController>().InstancePerRequest();
        var container = builder.Build();
        var resolver = new AutofacWebApiDependencyResolver(container);
        GlobalConfiguration.Configuration.DependencyResolver = resolver;

But it seems that I am missing something cause I get the following error: An error occurred when trying to create a controller of type 'UsersController'. Make sure that the controller has a parameterless public constructor.

Popular Answer

You need to overwrite default controller activator, because it has no knowledge of your DI container.

Add a service class:

public class ServiceActivator : IHttpControllerActivator
{
    public ServiceActivator(HttpConfiguration configuration) { }

    public IHttpController Create(HttpRequestMessage request
        , HttpControllerDescriptor controllerDescriptor, Type controllerType)
    {
        var controller = ObjectFactory.GetInstance(controllerType) as IHttpController;
        return controller;
    }
}

Then on Application_Start():

GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new ServiceActivator(GlobalConfiguration.Configuration));

I'm using structure map in this example, so just replace it with which ever container you are using.



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why