Skip to content

Instantly share code, notes, and snippets.

@jpoehls
Last active December 26, 2015 18:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpoehls/7197702 to your computer and use it in GitHub Desktop.
Save jpoehls/7197702 to your computer and use it in GitHub Desktop.
Basic ASP.NET MVC controller / data layer interaction architecture example.
class GadgetController : Controller {
// Each MVC controller has a complementing '*ControllerContext' class.
private readonly IGadgetControllerContext _context;
GadgetController()
: this(new GadgetControllerContext()) { }
// Unit testing ctor. Allows passing in mock repositories.
GadgetController(IGadgetControllerContext context) {
_context = context;
}
ActionResult Index() {
ViewData["gadgets"] = _context.GadgetRepo.GetAll();
return View();
}
}
// Controller Context class for the Gadget controller.
// Provides access to the data repositories needed by the controller.
// Inherits from the base MyAppControllerContext which provides
// the underlying data context / session / connection stuff.
class GadgetControllerContext : MyAppControllerContext, IGadgetControllerContext {
private readonly IGadgetRepository _gadgetRepo;
GadgetControllerContext() {
_gadgetRepo = new GadgetRepository(base.DbSession);
}
IGadgetRepository GadgetRepo { get { return _gadgetRepo; } }
}
// Data access repository for Gadgets.
// Follows the repository pattern, for better or worse.
class GadgetRepository : IGadgetRepository {
// TODO: Replace IDbSession with your DataContext or whatever.
private readonly IDbSession _session;
GadgetRepository(IDbSession session) {
_session = session;
}
IEnumerable<Gadget> GetAll() {}
}
interface IGadgetControllerContext {
IGadgetRepository GadgetRepo { get; }
}
interface IGadgetRepository {
IEnumerable<Gadget> GetAll;
}
// Base class for all *ControllerContext classes.
// Handles opening/closing the underlying data connections/sessions/etc.
class MyAppControllerContext {
// TODO: Replace IDbSession with your DataContext or whatever.
IDbSession DbSession { get { return GetSessionForHttpContext(HttpContext.Current); } }
// TODO: This is also a great place for things like AppSettings, etc.
/// <summary>
/// Gets a per-request database unit of work session
/// </summary>
/// <author>Joshua Poehls</author>
public static IDbSession GetSessionForHttpContext(HttpContext ctx)
{
return GetSessionForHttpContext(new HttpContextWrapper(ctx));
}
private const string DbContextHttpContextItemKey = "MyAppControllerContext.DbSession";
/// <summary>
/// Gets a per-request database unit of work session
/// </summary>
/// <author>Joshua Poehls</author>
public static IDbSession GetSessionForHttpContext(HttpContextBase ctx)
{
Debug.Assert(ctx != null);
if (!ctx.Items.Contains(DbContextHttpContextItemKey))
{
var dbCtx = new MyAppDbContext();
ctx.Items.Add(DbContextHttpContextItemKey, dbCtx);
if (DbSessionInit != null)
{
DbSessionInit(dbCtx, new DbSessionInitEventArgs(dbCtx));
}
}
return (MyAppDbContext)ctx.Items[DbContextHttpContextItemKey];
}
// TODO: Call DisposeSessionForHttpContext() on Application.EndRequest!
// The MyAppControllerContextModule HttpModule does this for you if you wire it up.
/// <summary>
/// Disposes any DB context that was created for the
/// given <see cref="HttpContext"/>.
/// </summary>
/// <author>Joshua Poehls</author>
public static void DisposeSessionForHttpContext(HttpContext ctx)
{
Debug.Assert(ctx != null);
if (ctx.Items.Contains(DbContextHttpContextItemKey))
{
var db = (MyAppDbContext)ctx.Items[DbContextHttpContextItemKey];
if (db != null)
{
db.Dispose();
}
ctx.Items.Remove(DbContextHttpContextItemKey);
}
}
}
/// <summary>
/// Handles disposing the <see cref="MyAppControllerContext"/> object's session when the request ends.
/// </summary>
/// <author>Joshua Poehls</author>
public class MyAppControllerContextModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.EndRequest += Application_EndRequest;
}
private static void Application_EndRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
MyAppControllerContext.DisposeSessionForHttpContext(app.Context);
}
public void Dispose() { }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment