I've been working on a project based off of this tutorial. Unfortunately, the controller classes in this are quite dense and have terrible separation of concerns. I should have realized this originally but, I ran with it and now am stuck dealing with the terrible design from this tutorial with my added features/bad decisions.In my case, I have 3 controllers: Hardware, Employee, Project. They access the database, filter the data and pass them along to the view. I also create certain UI components in the controller (see SelectList in example below).I've been reading about Dependency Injection, the Repository pattern and the Unit of Work pattern. I'm confused a bit towards all 3 of these, but I tend to agree with Repository is the new Singleton. If this is what EF6 does, I don't think it's a good idea to re-implement it. I think DI is definitely where I should be headed but I think my comprehension of it isn't quite there yet.I want to break down these controllers into smaller, reusable parts. Filtering for example, could be re-used by different models but I can't quite abstract this in my head. There's a lot going on in most controllers:public class HardwareController : Controller{    private LATTContext db = new LATTContext();    // GET: Hardware    public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page)    {        ViewBag.CurrentSort = sortOrder;        ViewBag.SerialNoParm = sortOrder == serialNo ? serialNo_desc : serialNo;        ViewBag.CabModelParm = sortOrder == cabModel ? cabModel_desc : cabModel;        ViewBag.PlatformParm = sortOrder == plat ? plat_desc : plat;        ViewBag.VendorParm = sortOrder == vendor ? vendor_desc : vendor;        ViewBag.CategoryParm = sortOrder == category ? category_desc : category;        ViewBag.EmployeeParm = sortOrder == employee ? employee_desc : employee;        if (searchString != null)        {            page = 1;        }        else        {            searchString = currentFilter;        }        ViewBag.CurrentFilter = searchString;        var hardwares = from h in db.hardwares                        select h;        if (!String.IsNullOrEmpty(searchString))        {            hardwares = hardwares.Where(h => h.SerialNo.ToLower().Contains(searchString.ToLower()) ||                h.model.Name.ToLower().Contains(searchString.ToLower()) ||                h.platform.Name.ToLower().Contains(searchString.ToLower()) ||                h.vendor.Name.ToLower().Contains(searchString.ToLower()) ||                h.category.Type.ToLower().Contains(searchString.ToLower()));        }        switch (sortOrder)        {            case serialNo:                hardwares = hardwares.OrderBy(h => h.SerialNo);                break;            case serialNo_desc:                hardwares = hardwares.OrderByDescending(h => h.SerialNo);                break;            case cabModel:                hardwares = hardwares.OrderBy(h => h.model.Name);                break;            case cabModel_desc:                hardwares = hardwares.OrderByDescending(h => h.model.Name);                break;            case plat:                hardwares = hardwares.OrderBy(h => h.platform.Name);                break;            case plat_desc:                hardwares = hardwares.OrderByDescending(h => h.platform.Name);                break;            case vendor:                hardwares = hardwares.OrderBy(h => h.vendor.Name);                break;            case vendor_desc:                hardwares = hardwares.OrderByDescending(h => h.vendor.Name);                break;            case category:                hardwares = hardwares.OrderBy(h => h.category.Type);                break;            case category_desc:                hardwares = hardwares.OrderByDescending(h => h.category.Type);                break;            case employee:                hardwares = hardwares.OrderBy(h => h.employee.FirstName);                break;            case employee_desc:                hardwares = hardwares.OrderByDescending(h => h.employee.FirstName);                break;            default:                hardwares = hardwares.OrderBy(h => h.model.Name);                break;        }        int pageSize = 10;        int pageNumber = (page ?? 1);        return View(hardwares.ToPagedList(pageNumber, pageSize));    }    // GET: Hardware/Details/5    public ActionResult Details(int? id)    {        if (id == null)        {            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);        }        Hardware hardware = db.hardwares.Find(id);        if (hardware == null)        {            return HttpNotFound();        }        return View(hardware);    }    // GET: Hardware/Create    public ActionResult Create()    {        ViewBag.Category_ID = new SelectList(db.categories, CategoryID, Type);        ViewBag.Employee_ID = new SelectList(db.employees, EmployeeID, FullName);        ViewBag.Model_ID = new SelectList(db.models, CabinetModelID, Name);        ViewBag.Platform_ID = new SelectList(db.platforms, PlatformID, Name);        ViewBag.Vendor_ID = new SelectList(db.vendors, VendorID, Name);        return View();    }    // POST: Hardware/Create    // To protect from overposting attacks, please enable the specific properties you want to bind to, for     // more details see http://go.microsoft.com/fwlink/?LinkId=317598.    [HttpPost]    [ValidateAntiForgeryToken]    public ActionResult Create([Bind(Include = HardwareID,SerialNo,Comment,Platform_ID,Category_ID,Vendor_ID,Model_ID,Employee_ID)] Hardware hardware)    {        try        {            if (ModelState.IsValid)            {                db.hardwares.Add(hardware);                db.SaveChanges();                return RedirectToAction(Index);            }        }        catch (DbUpdateException /*ex*/)        {            ModelState.AddModelError(, Problem updating database. Please verify that Serial No is unique);        }        ViewBag.Category_ID = new SelectList(db.categories, CategoryID, Type, hardware.Category_ID);        ViewBag.Employee_ID = new SelectList(db.employees, EmployeeID, FullName, hardware.Employee_ID);        ViewBag.Model_ID = new SelectList(db.models, CabinetModelID, Name, hardware.Model_ID);        ViewBag.Platform_ID = new SelectList(db.platforms, PlatformID, Name, hardware.Platform_ID);        ViewBag.Vendor_ID = new SelectList(db.vendors, VendorID, Name, hardware.Vendor_ID);        return View(hardware);    }    // GET: Hardware/Edit/5    public ActionResult Edit(int? id)    {        if (id == null)        {            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);        }        Hardware hardware = db.hardwares.Find(id);        if (hardware == null)        {            return HttpNotFound();        }        ViewBag.Category_ID = new SelectList(db.categories, CategoryID, Type, hardware.Category_ID);        ViewBag.Employee_ID = new SelectList(db.employees, EmployeeID, FullName, hardware.Employee_ID);        ViewBag.Model_ID = new SelectList(db.models, CabinetModelID, Name, hardware.Model_ID);        ViewBag.Platform_ID = new SelectList(db.platforms, PlatformID, Name, hardware.Platform_ID);        ViewBag.Vendor_ID = new SelectList(db.vendors, VendorID, Name, hardware.Vendor_ID);        return View(hardware);    }    // POST: Hardware/Edit/5    // To protect from overposting attacks, please enable the specific properties you want to bind to, for     // more details see http://go.microsoft.com/fwlink/?LinkId=317598.    [HttpPost]    [ValidateAntiForgeryToken]    public ActionResult Edit([Bind(Include = HardwareID,SerialNo,Comment,Platform_ID,Category_ID,Vendor_ID,Model_ID,Employee_ID)] Hardware hardware)    {        if (ModelState.IsValid)        {            db.Entry(hardware).State = EntityState.Modified;            db.SaveChanges();            if (Request.UrlReferrer.ToString().Contains(hardware/Edit))            {                return RedirectToAction(Index);            }            else            {                return RedirectToAction(Index, Project);            }        }        ViewBag.Category_ID = new SelectList(db.categories, CategoryID, Type, hardware.Category_ID);        ViewBag.Employee_ID = new SelectList(db.employees, EmployeeID, FirstName, hardware.Employee_ID);        ViewBag.Model_ID = new SelectList(db.models, CabinetModelID, Name, hardware.Model_ID);        ViewBag.Platform_ID = new SelectList(db.platforms, PlatformID, Name, hardware.Platform_ID);        ViewBag.Vendor_ID = new SelectList(db.vendors, VendorID, Name, hardware.Vendor_ID);        return View(hardware);    }    // GET: Hardware/Delete/5    public ActionResult Delete(int? id)    {        if (id == null)        {            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);        }        Hardware hardware = db.hardwares.Find(id);        if (hardware == null)        {            return HttpNotFound();        }        return View(hardware);    }    // POST: Hardware/Delete/5    [HttpPost, ActionName(Delete)]    [ValidateAntiForgeryToken]    public ActionResult DeleteConfirmed(int id)    {        //TODO catch inner sql exception when hardware is assigned        if (ModelState.IsValid)        {            Hardware hardware = db.hardwares.Find(id);            db.hardwares.Remove(hardware);            db.SaveChanges();        }        return RedirectToAction(Index);    }    protected override void Dispose(bool disposing)    {        if (disposing)        {            db.Dispose();        }        base.Dispose(disposing);    }}
Controllers and Separation of Concerns: discussing possible strategies
design;web development;asp.net mvc;entity framework