Search code examples
c#autofac

Cannot Implicilty Convert Type - Autofac C# & ASP.NET MVC


I have a fairly simple ASP.NET MVC app that I am trying to resolve some dependencies in my controller. I have casting problems with List and I am not sure what to do at this moment. I have read about the Resolve() method with Autofac, but again I am not sure if this will resolve my particular issue.

Here is my controller code:

public class NumbersController : Controller
{
    private INumbersModel _model;
    private INumbersBusinessLayer _numbersBusinessLayer;
    private IEnumerable<INumbersModel> _modelList;

    public NumbersController(INumbersModel model, IEnumerable<INumbersModel> modelList, INumbersBusinessLayer numbersBusinessLayer)
    {
        _model = model;
        _numbersBusinessLayer = numbersBusinessLayer;
        _modelList = new List<INumbersModel>(modelList);
    }

    public ActionResult Index()
    {
        _modelList = _numbersBusinessLayer.AllNumbers.ToList();
        return View(_modelList);
    }    

    [HttpGet]
    public ActionResult Edit(int id)
    {
        _model = _numbersBusinessLayer.AllNumbers.Single(n => n.ID == id);
        return View(_model);
    }
}

Here are my two interfaces:

public interface INumbersBusinessLayer
{
        IEnumerable<NumbersModel> AllNumbers { get; }

        void AddNumbers(NumbersModel model);
        void DeleteNumbers(int id);
        void UpdateNumbers(NumbersModel model);
}

public interface INumbersModel
{
        int ID { get; set; }
        bool IsValid { get; set; }
        string Numbers { get; set; }
        string Order { get; set; }
        string Time { get; set; }
}

Here is my container config:

public static void ConfigureDependencyInjection()
{
    var builder = new ContainerBuilder();

    // ...or you can register individual controlllers manually.
    builder.RegisterType<NumbersController>().InstancePerRequest();

    // register models
    builder.RegisterType<NumbersModel>().As<INumbersModel>();
    builder.RegisterType<List<NumbersModel>>().As<List<INumbersModel>>();
    builder.RegisterType<NumbersBusinessLayer>().As<INumbersBusinessLayer>();

    IContainer container = builder.Build();

    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}

In the browser I get this error:

The type 'System.Collections.Generic.List1[BusinessLayer.NumbersModel]' is not assignable to service 'System.Collections.Generic.List1[[BusinessLayer.INumbersModel, BusinessLayer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'.


Solution

  • You should only need to register your INumbersBusinessLayer, since that is the only thing you actually need to inject into your controller.

    Furthermore, change INumbersModel to a class, so you can use it.

    So your controller then looks like this:

    public class NumbersController : Controller
    {
        private INumbersBusinessLayer _numbersBusinessLayer;
    
        public NumbersController(INumbersBusinessLayer numbersBusinessLayer)
        {
            _numbersBusinessLayer = numbersBusinessLayer;
        }
    
        public ActionResult Index()
        {
           var  modelList = _numbersBusinessLayer.AllNumbers.ToList();
    
            return View(modelList);
        }
    
        [HttpGet]
        public ActionResult Edit(int id)
        {
            var model = _numbersBusinessLayer.AllNumbers.Single(n => n.ID == id);
    
            return View(model);
        }
    }
    

    Then you can simplify your AutoFac config:

    public static void ConfigureDependencyInjection()
    {
        var builder = new ContainerBuilder();
        // ...or you can register individual controlllers manually.
        builder.RegisterType<NumbersController>().InstancePerRequest();
        builder.RegisterType<NumbersBusinessLayer>().As<INumbersBusinessLayer>();
    
        IContainer container = builder.Build();
    
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    }
    

    and change your interface to a class:

    public class NumbersModel
    {
        int ID { get; set; }
        bool IsValid { get; set; }
        string Numbers { get; set; }
        string Order { get; set; }
        string Time { get; set; }
    }
    

    Since your businesslayer interface already expects Numbersmodel, but not INumbersmodel, no changes are needed there.