views:

48

answers:

2

I have CompanyController and DepartmentController:

public class CompanyController : BaseBackendController
{
   private ICompanyRepository repository;
   public CompanyController(ICompanyRepository repository)
   {
     this.repository = repository;
   }

  ...
   [HttpPost]
   public ActionResult BatchDelete(long[] ids)
   {

     var entities = repository.GetList().Where(item => ids.Contains(item.ID));

     repository.BatchDelete(entities);
     return RedirectToAction("Index");
   }
}

public class DepartmentController : BaseBackendController
{
   private IDepartmentRepository repository;
   public DepartmentController(IDepartmentRepository repository)
   {
     this.repository = repository;
   }

  ...
   [HttpPost]
   public ActionResult BatchDelete(long[] ids)
   {

     var entities = repository.GetList().Where(item => ids.Contains(item.ID));

     repository.BatchDelete(entities);
     return RedirectToAction("Index");
   }
}

You can see that logic of BatchDelete is the same and I want it place to parent controller, but there is a challenge, the repository. I cant call in base controller repository.GetList().

+2  A: 

You have to have some commonality in your repository interface. For example, you could this do:

public interface IRepository<T>
{
    IEnumerable<T> GetList();
    void DeleteBatch(IEnumerable<T> entities);
    // other methods here
}

where you have:

public interface ICompanyRepository : IRepository<T>

and

public interface IDepartmentRepository : IRepository<T>

Then you can set up your base controller like this:

public abstract class DataController<TModel> : Controller
{
    protected IRepository<TModel> repository;

    public DataController(IRepository<TModel> repository)
    {
        this.repository = repository;
    }

   [HttpPost]
   public ActionResult BatchDelete(long[] ids)
   {

     var entities = repository.GetList().Where(item => ids.Contains(item.ID));

     repository.BatchDelete(entities);
     return RedirectToAction("Index");
   }
}

UPDATE Then your CompanyController will look like this:

public CompanyController : DataController<Company>
{
    public CompanyController(IRepository<Company> repository) : base(repository)
    {
    }
}

This will do the trick.

One other note of caution it looks like your GetList() is getting all entites from the database and then select the one you want to delete for the delete operation. Better to retrieve only the one you are interested from the database and save significant performance.

Steve Michelotti
nice! but i am in doubt how CompanyController ctor will be look?
eldar
I updated the above answer with the code for the CompanyController as well.
Steve Michelotti
if I have specific method say in ICompanyRepository. how can I call it from CompanyController? I dont want declare it in IRepostiory
eldar
to previous comment: it will work if I explicitly hide the repository field in controller "private new ICompanyRepository repository;"
eldar
Don't make it "private new" - instead make the scope "protected" instead of "private" the base controller. This will allow you to access from the CompanyController for those methods that are specific to this repository.
Steve Michelotti
in your answer "private IRepository<TModel> repository;" - so I cant access repository from derived controllers. And I still cant call specific methods in ICompanyRepository because according to your answer IRepository<TModel> passes to DataController - so the type of field "repository" is IRepository<Company> not ICompanyRepository, that is i get compile error, Any thoughts?
eldar
@eldar - In my last comment I specifically said to change the access of that to "protected" so that you could see if from the derived controller - I'll update the code in my answer to make that more clear. For your second issue, you can create a property in your controller which encapsulates it with a cast like this:
Steve Michelotti
private ICompanyRepository Repository { get { return this.repository as ICompanyRepository; } }
Steve Michelotti
Thank you very much!
eldar
+1  A: 

This, children, is why we pass services to Controllers, not raw repositories.

Wyatt Barnett