Controller with same structure not working using an interface

360 views Asked by At

I have created 8 models and controllers respectively for my Project using the same structure, however now this structure is not working. It is giving me this error:

The current type, HelpDesk.Contracts.Repositories.IRepositoryBase`1[HelpDesk.Model.Knowledgebase], is an interface and cannot be constructed. Are you missing a type mapping?

Here is my interface:

    namespace HelpDesk.Contracts.Repositories
{
    public interface IRepositoryBase<TEntity>
     where TEntity : class
    {
        void Commit();
        void Delete(object id);
        void Delete(TEntity entity);
        System.Linq.IQueryable<TEntity> GetAll();
        System.Linq.IQueryable<TEntity> GetAll(object filter);
        TEntity GetById(object id);
        TEntity GetFullObject(object id);
        System.Linq.IQueryable<TEntity> GetPaged(int top = 20, int skip = 0, object orderBy = null, object filter = null);
        void Insert(TEntity entity);
        void Update(TEntity entity);
    }
}

Here is my controller:

namespace HelpDesk.WebUI.Controllers
{
    public class KnowledgebaseController : Controller
    {

        private DataContext db = new DataContext();

        IRepositoryBase<Knowledgebase> knowledgebases;

        public KnowledgebaseController(IRepositoryBase<Knowledgebase> knowledgebases)
        {
            this.knowledgebases = knowledgebases;
        }

public ActionResult ChooseSearchView()
        {
            string r = Session["LoggedUserRole"].ToString();

            if (r == "Technician")
            {
                return RedirectToAction("TechKnowledgebaseSearch");
            }
            else
            {
                return RedirectToAction("UserKnowledgebaseSearch");
            };

        }

My DataContext:

namespace HelpDesk.Contracts.Data
{
    public class DataContext : DbContext
    {
        /// <summary>
        /// you can either pass the NAME of a connection string (e.g. from a web.
        /// ), and explicitly i
        ///  </summary>
        public DataContext() : base("HelpDesk")
        {
        }

        /// <summary>
        /// any entity to be persisted must be declared here.
        /// </summary>
        /// 
        public DbSet<Category> Categories { get; set; }
        public DbSet<Knowledgebase> Knowledgebases { get; set; }
        public DbSet<Problem> Problems { get; set; }
        public DbSet<Role> Roles { get; set; }
        public DbSet<Ticket> Tickets { get; set; }
        public DbSet<TicketNote> TicketNotes { get; set; }
        public DbSet<TicketStatus> TicketStatuses { get; set; }
        public DbSet<TicketSubscription> TicketSubscriptions { get; set; }
        public DbSet<User> Users { get; set; }


    }
}

Here is the repositorybase:

 namespace HelpDesk.Contracts.Repositories
{
    public abstract class RepositoryBase<TEntity> : HelpDesk.Contracts.Repositories.IRepositoryBase<TEntity> where TEntity : class
    {
        internal DataContext context;
        internal DbSet<TEntity> dbSet;

        public RepositoryBase(DataContext context)
        {
            this.context = context;
            this.dbSet = context.Set<TEntity>();
        }

        public virtual TEntity GetById(object id)
        {
            return dbSet.Find(id);
        }

        public virtual IQueryable<TEntity> GetAll()
        {
            return dbSet;
        }

        public IQueryable<TEntity> GetPaged(int top = 20, int skip = 0, object orderBy = null, object filter = null)
        {
            return null; // need to override in order to implement specific filtering and ordering
        }

        public virtual IQueryable<TEntity> GetAll(object filter)
        {
            return null; //need to override in order to implement specific filtering
        }

        public virtual TEntity GetFullObject(object id)
        {
            return null; //need to override in order to implement specific obect graph.
        }

        public virtual void Insert(TEntity entity)
        {
            dbSet.Add(entity);
        }

        public virtual void Update(TEntity entity)
        {
            dbSet.Attach(entity);
            context.Entry(entity).State = EntityState.Modified;
        }

        public virtual void Delete(TEntity entity)
        {
            if (context.Entry(entity).State == EntityState.Detached)
                dbSet.Attach(entity);

            dbSet.Remove(entity);
        }

        public virtual void Delete(object id)
        {
            TEntity entity = dbSet.Find(id);

        }

        public virtual void Commit()
        {
            context.SaveChanges();
        }

        public virtual void Dispose()
        {
            context.Dispose();
        }

    }
}

Here I have a similar structured Controller that works just fine and another 7 like that:

namespace HelpDesk.WebUI.Controllers
{
    public class RoleController : Controller
    {

        private DataContext db = new DataContext();

        IRepositoryBase<Role> roles;

        public RoleController(IRepositoryBase<Role> roles)
        {
            this.roles = roles;
        }

The Exception is thrown when I click on this link:

<li>@Html.ActionLink("Knowledgebase", "ChooseSearchView", "Knowledgebase")</li>
2

There are 2 answers

0
Oluwafemi On BEST ANSWER

Update your KnowledgebaseController constructor to this:

public KnowledgebaseController()
        {
            this.knowledgebases = new RepositoryBase<Knowledgebase>(db);
        }

and remove abstract from the RepositoryBase<TEntity> class in order to make it instantiable.

Please note: This is just a quick fix. To implement a much solid architecture which facilitates easy unit testing and loosely coupled classes, I would suggest you implement a unit of work. Follow this link Repository Pattern and Unit of Work with Entity Framework in ASP.NET MVC

8
ragerory On

You can't instantiate an interface, you have to instantiate a class that implements that interface.

public class RepositoryBase<T> : IRepositoryBase
{
    public RepositoryBase<T>()
    {
    }
    ...
}

Then instantiate your concrete class with that type

IRepositoryBase<Knowledgebase> knowledgebases = new RepositoryBase<Knowledgebase>();

Read more about interfaces and instantiation here: Using Interfaces