So I have an ASP.NET MVC 5 app with ASP.NET Identity 2.0 running. Everything is pretty okay, but I want to refactor my code and I am wondering what alternatives exist to my current implementation. Let me explain.
I have the Controllers in the root of my project as well as many in the Areas folder of the project. Nearly all of them inherit from a BaseController
class, which in turn inherits from System.Web.Mvc.Controller
. This BaseController
looks something like this:
public class BaseController()
{
protected ApplicationUserManager _userManager;
protected ApplicationRoleManager _roleManager;
protected readonly MyDbContext _db = new MyDbContext();
public BaseController()
{
}
public BaseController(ApplicationUserManager um, ApplicationRoleManager rm)
{
UserManager = um;
RoleManager = rm;
}
public ApplicationUserManager UserManager { ... }
public ApplicationRoleManager RoleManager { ... }
#region Utility Methods
// Here are over 60 utility methods that are basically queries on _db
#endregion
}
More methods are on the way and I can't help but feel there is a better way than having them in a base class when logically, not every controller should directly inherit such methods.
Moving them to MyDbContext
(inherits IdentityDbContext
) essentially does nothing but move them to a more applicable file. What I'm imagining is having custom utility methods for each DbSet in MyDbContext
but I'm not sure how to do that. Something like the following would be ideal:
Semester thisSemester = _db.Semesters.GetCurrentSemester();
or
SelectList semesters = _db.Semesters.GetAllSemestersAsSelectList();
where Semesters
is of type DbSet<Semester>
in both examples.
Can anyone offer a solution?
When I see a method like...
_db.Semesters.GetAllSemestersAsSelectList()
...I think this would be an extension method (unless you have your own implementation of DbSet
). But extension methods are intended for really universal tasks, not for such specific tasks. Moreover, it requires that anywhere where you want this select list you have access tot the DbSet
It's better to do this in a service class so you can call a method like
_semesterService.GetAllSemestersAsSelectList()
This service could look like
class SemesterService : ISemesterService
{
private readonly MyDbContext _context;
/// <summary>
/// Constructor in which an IoC container can inject a context.
/// </summary>
/// <param name="context"></param>
public SemesterService(MyDbContext context)
{
this._context = context;
}
public SelectList GetAllSemestersAsSelectList()
{
return new SelectList(_context.Semesters, "Id", "Name");
}
public Semester GetCurrentSemester()
{
return _context.Semesters.Where(....).FirstOrDefault();
}
}
Just to give you an example.
Probably it's even better to just return Semesters from the service and build the SelectList
in the MVC controller, so the service layer won't have a dependency to MVC.